Search code examples
wpfuser-interfaceasynchronousdispatcherbegininvoke

Keeping the UI visually updated while running an expensive operation on the UI thread


In my WPF app, I need to run an expensive operation on my UI thread (let's call it ExpensiveUIOperation()), and I want to keep the UI up to date to track it's progress.

To track progress, I simply have a TextBlock, whose Text property is bound to an integer dependency property PercentageComplete. During ExpensiveUIOperation(), I simply set the value of PercentageComplete as required.

Now, I understand enough about threading to know that if I simply ran ExpensiveUIOperation() on my UI thread, that the TextBlock would not appear to keep up to date, as the UI thread would be blocked, stopping any interface updates.

And so I thought I could do it asynchronously like this:

Dispatcher.BeginInvoke(new Action(ExpensiveUIOperation), DispatcherPriority.Background);

But that is still not working. The text block is not visually updated until the operation completes.

Is there a way to do this?

Unfortunately in this situation I cannot use a background thread, as the operation makes heavy use of objects owned by the UI thread.


Solution

  • You're stuck, UI operations have to occur on the UI thread, and while that occurs no UI updates will happen. You could do the equivalent of an Application.DoEvents in WPF by creating a new dispatcher frame (http://dedjo.blogspot.com/2007/08/how-to-doevents-in-wpf.html) but it is dangerous, you will catch the UI in the middle of updates and not a good thing to do.

    Is the expensive UI operation really a CPU-intensive, UI-only operation? Nothing that can be done with a View Model object graph and then finally bound to the UI, for example?