Quick: can you spot what’s wrong with this XAML?
<ProgressBar x:Name=”Progress” Visibility=”Collapsed” IsIndeterminate=”True” />
If you answered that setting IsIndeterminant to true on a ProgressBar control in Silverlight for Windows Phone debilitates performance, go to the head of the class! If not, read on.
If you use Silverlight for Windows Phone’s networking stack to download content or call Web services, you probably use the ProgressBar control a lot. If you’re downloading content with a WebClient, you may not use the ProgressBar’s IsIndeterminant property, because WebClient fires DownloadProgressChanged events that you can use to step the ProgressBar and keep the user informed about the progress of the download. But if you’re using HttpWebRequest to call REST services or Web-service proxies to call WCF services, you typically set the ProgressBar’s IsIndeterminant property true to display those running blue dots seen in applications such as Microsoft’s Facebook client for Windows Phone. It’s a nice thing to do from a UI perspective, because once you put a call on the wire, you have no control over how long it takes to complete. Rather than leave the user staring at a blank screen, the indeterminant ProgressBar lets the user know that you’re waiting for a network call to complete.
But there’s a problem. A ProgressBar running in indeterminant mode in Silverlight for Windows Phone sucks up CPU time. Worse, it sucks up CPU time on the UI thread rather than the dedicated composition thread, due to the creative way in which the control was implemented. Worse still, it continues to bang on the CPU even when the ProgressBar isn’t visible! More than one phone developer has noticed that his or her application is running slugglishly, traced it back to the presence of a ProgressBar, and wondered what the heck is going on.
Jeff Wilcox, a senior software developer at Microsoft, has documented this problem – and solutions – in an article entitled The High-Performance ProgressBar for Windows Phone and in a follow-up article. The recommended fix is to use Jeff’s PerformanceProgressBar control rather than ProgressBar. But at the very least, if you use the built-in ProgressBar, be sure to set IsIndeterminant to false anytime the control is hidden. I routinely do this now when launching an asynchronous network request:
// Show the progress bar
Progress.IsIndeterminate = true;
Progress.Visibility = Visibility.Visible;
And this when the call completes:
// Hide the progress bar
Progress.IsIndeterminate = false;
Progress.Visibility = Visibility.Collapsed;
One of the items on my to-do list is to go back and replace all my ProgressBars with PerformanceProgressBars. After all, a UI thread is a precious thing to waste.
Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…
Cloud management is difficult to do manually, especially if you work with multiple cloud…
Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…
https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…
FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…
Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…
View Comments
PingBack from http://topsy.com/training.atmosera.com/CS/blogs/jprosise/archive/2011/02/08/silverlight-for-windows-phone-programming-tip-5.aspx?utm_source=pingback&utm_campaign=L2
PerformanceProgressBar is not a solution either. It is better than standard ProgressBar, but it still takes about 50% of the CPU resources. In fact any Storyboard animation will behave identically.
See http://www.codeproject.com/KB/showcase/WP7-Animations.aspx for reasoning and alternatives.
@Jan: Great article! I'll have to say that I was surprised by the relatively positive performance of the DispatcherTimer approach. I would have guessed it would be lower.
Thanks. I tried to pass this info to Jeff Wilcox long time ago...
Jeff,
you said "I routinely do this now when launching an asynchronous network request"
I have a problem disabling it when content is loaded.
Simply I have a page with a list.
I bind the list to the ContentClass.ObsObject
The content class (separated from the page) has a method to load the XML data from the server.
This is done via HTTPRequest so is Asyncronous.
The call back function will populate the ObsObject list so that the binded object will fill up.
The issue is that if I try to put the
// Hide the progress bar
Progress.IsIndeterminate = false;
Progress.Visibility = Visibility.Collapsed;
In the call back I get a "Reference to a non shared member requires an object reference".
How can I solve it?
(sorry for newbie question)
Are you trying to update the progress bar from the HttpWebRequest completion method? If so, it won't work because that method executes on a background thread. Use Dispatcher.BeginInvoke to get back to the UI thread to hide the progress bar and it'll work a lot better.
Thank you for great review