Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProgressBar Indeterminate has a high CPU usage (even when collapsed) #1509

Closed
Safirion opened this issue Aug 2, 2019 · 10 comments
Closed

ProgressBar Indeterminate has a high CPU usage (even when collapsed) #1509

Safirion opened this issue Aug 2, 2019 · 10 comments
Labels
Bug Product bug (most likely)

Comments

@Safirion
Copy link

Safirion commented Aug 2, 2019

  • .NET Core Version: 3.0 Preview7
  • Windows version: Certainly all but tested on Windows Server 2016 and Windows 10 1903
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

Problem description:

Progress bar with IsIndeterminate=true has a high CPU usage when collapsed.

image

As we can see, I have ~10-15% of CPU usage for a ProgressBar in collapsed stackpanel (and up to 50% of CPU usage on VM with only 2 vcpu). I notice that every time I paused the process, the main thread is on "WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW"

My current workaround for this situation is when I collapse my StackPanel, I set also the IsIndeterminate property of my progressbar to false.

Actual behavior:
ProgressBar indeterminate has high usage of CPU when collapsed.

Expected behavior:
ProgressBar indeterminate has no impact on CPU when collapsed.

Obviously, the best scenario should be that indeterminate progress bar has no impact on CPU even when visible... But animation has a cost, I know that...

Minimal repro:

<StackPanel x:Name="LoadingPanel">
          <ProgressBar IsIndeterminate="True" />
</StackPanel>

Display LoadingPanel in a Window and collapse LoadingPanel.

@mdtauk
Copy link

mdtauk commented Aug 2, 2019

Could this be because you are not setting IsIndeterminate to False before collapsing?

@Safirion
Copy link
Author

Safirion commented Aug 2, 2019

Yes it is. But this is, in my sens, a workaround : is this behavior really wanted ?

Before the first display of the progress bar, there is no cpu usage at all.

In my application, at the beginning, my indeterminate progress bar is in the collapsed stackpanel, then I have a loading so I set the stackpanel visible and then I want to just collapse again my stackpanel when the loading is finished.

For me, it's a non sens that the progressbar in the collapsed stackpanel suddenly use cpu when it don't do that just before displaying it first time.

@mdtauk
Copy link

mdtauk commented Aug 2, 2019

Not sure the implications for changing this behaviour at the framework level (handling the animation of controls when Visibility is set to Hidden, Collapsed, Opacity 0%).

Or should the control end the animation when it's Visibility is set to Collapsed?

Which change has the most benefit vs changing existing apps and behaviour?

@weltkante
Copy link

weltkante commented Aug 2, 2019

Its a bug and not limited to Visibility=Collapsed. You can remove the progress bar from the stack panel and it will still keep trying to animate, even though there is nothing left to animate. I debugged that very same issue in ILSpy once, see icsharpcode/ILSpy#593 - quoting for reference:

A control in a container with Visibility=Collapsed still gets animated? I'd call that a WPF bug.

This actually looks like a really nasty bug, not limited to Visibility=Collapsed. I made a test application with just a panel and a progress bar, once the progress bar starts animating WPF will never drop back out of 60 fps rendering except when turning the animation explicitely off by setting IsIndeterminate=false. Even removing the progress bar from the visual tree keeps WPF rendering at 60 fps, even though the visual tree never gets invalidated any more. I wonder if you can get stuck in 60 fps mode if an animated object is garbage collected.

My understanding is that the WPF rendering engine has two modes, in the default mode it will just render on demand when you update something in the visual tree. If you start animating then WPF switches to a 60 fps rendering mode where it continously recalculates to produce smooth animations (which is really CPU hungry especially when running in a VM or over RDP). Apparently there is a bug which doesn't properly detect when animations are gone and its time to turn this 60 fps mode off, so it can easily happen that you are stuck in the 60 fps animation mode even if there isn't anything left to animate in the visual tree.

There are a lot of scenarios where you don't have full access to all controls in the visual tree, in particular when you are using 3rd party controls or themes. If you have styles or templates its sometimes really hard to get hold of the right thing to turn the animation off.

I think the period up to the dotnet 5 release is a good time to investigate and improve the animation system of WPF, it feels very crude and unnecessarily CPU hungry.

@Safirion
Copy link
Author

Safirion commented Aug 2, 2019

I don't think that playing an animation on an invisible control has a great interest. But it is true that some existing applications may have been based on this behavior to do other things.

So maybe just applying a patch for the progressbar should be great ? This could have a good impact on applications whose developers have not noticed this CPU activity. (I haven't noticed that before running my app on a old server VM of my society...)

@grubioe grubioe added this to the Future milestone Aug 6, 2019
@grubioe grubioe added the Bug Product bug (most likely) label Aug 6, 2019
@Symbai
Copy link
Contributor

Symbai commented Aug 7, 2019

I don't think that playing an animation on an invisible control has a great interest. But it is true that some existing applications may have been based on this behavior to do other things.

If we speak about .NET 5, breaking changes are expected to happen. It's a big new thing and the cases where you would want to continue animate something which is not visible at all are too few to provide compatibility. I would love to see this getting fixed once for all rather to apply specific patches for specific things. This "bug" should become an "opt-in" rather than "opt-out" in the whole WPF render engine and .NET 5 is indeed a good timing to do such a breaking change. Just my two cents.

@Safirion
Copy link
Author

Safirion commented Aug 7, 2019

If we speak about .NET 5, breaking changes are expected to happen.

If we speak about .NET 5, I totally agree with you 😉

@BieleckiLtd
Copy link

The longer I think about this the less buggy this behaviour look to me. Only because something has 0 opacity, is hidden or collapsed it does not meant it's not there and animation should stop. Indeterminate ProgressBar is just very specific case of animation that most of us would not care at what progress of animation it would re-appear if made visible back again. If the animation was something else, we would not like it to stop or pause when made not visible.

@weltkante
Copy link

weltkante commented Sep 29, 2020

The longer I think about this the less buggy this behaviour look to me.

Did you read my comment on this?

You can remove the progress bar from the stack panel and it will still keep trying to animate, even though there is nothing left to animate.

Animations will not be stopped automatically. WPF is designed to be garbage-collectible, so nothing implements IDisposable, yet animations must be stopped explicitly or will run forever.

Basically the animation engine is implemented independently of the rest of WPF and makes no assumption over what is visible, you can animate arbitrary properties. Seen in isolation its fine, but it conflicts massively with the dispose-less nature of WPF UI. IMHO its misdesigned and doesn't fit into the WPF world.

@dipeshmsft
Copy link
Member

This issue is resolved by the following PR #6266. So going ahead and closing the issue.

@ghost ghost removed this from the Future milestone May 10, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jun 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Product bug (most likely)
Projects
None yet
Development

No branches or pull requests

7 participants