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.