WPF is really awesome to build reactive applications and data binding is here to push useful information inside of the User Interface. All is done magically and it’s wonderfully simple to create an application without knowledge of the internals of the WPF’s rendering.
Now, I wan’t to talk about something which can useful in every WPF application : how to wait for the rendering UI to be done. This can also be rephrased to : “how to force the rendering after I performed an action ?“.
Why would I need this ?
You can find a lot of reasons to need this:
- You are doing a long-running job that can only be done on the UI thread (good bye BackgroundWorker) and you want to tell the user the progress of the task.
- The rendering of a control takes a lot of time to be done and you want to be sure that the “wait please” Textblock” is rendered instead of a white screen.
- You need to wait that the UI rendering following an action is done.
- You are a geek and you want to know how you can do this !
You are adding a lot of items to a binded collection and you want to wait for the rendering of each added item to be done. By doing this, the data won’t seems to be push into the ItemsControl by packet but one by one. No apparent freeze of the UI.As pointed out by a lot of people, there is really better ways to do this.
Here is a non-exhaustive list of things that can only be done on the UI-Thread and which are time-consuming (if you have some others, please give me them in the comments):
- Create UI controls may be long(exemple),
- Im my previous project using Mogre 3D, I needed to initialize some parts of the 3D engine in the main UI Thread,
- Sometimes applying the content to a view is very long because the XAML is really complex (more to come on this in a later post),
- etc.
Please tell me how can I do this !
What is wonderful is that the solution takes only one little line of code. One line of code.
To keep it simple, the rendering of the UI is perform on the UI thread via the Dispatcher. It can be considered as a tasks processer, each of these task being assigned a priority. The rendering of the UI is one of these tasks and all you have to do is tell the Dispatcher: “perform an action now with a priority less than the rendering”. The current work will then wait for the rendering to be done.
Here is the snippet this sentence transposing in .Net:
Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
I promised: only one line of code.
The code starts an empty action via the Dispatcher’s Invoke method. The priority given to the Dispatcher is ContextIdle which is lesser that Render so the Dispatcher will wait for the rendering to be done before to execute the empty action(I agree that waiting to do nothing is quite strange but..
).
Because the call to Invoke is blocking, your code won’t go on until the rendering is effectively done.
That is exactly what is required.
Wait… there is no drawback ?
Of course there is! And a big one named ‘performance’. By doing the calls to Dispatcher.Invoke, you are forcing a switch between thread execution and it costs a lot of processing which can be disastrous in term of performance. My disclaimer is so: do this only when necessary, really necessary.
By the way, you can quite easily limit the occurrence of the context switches by doing the call every X(where X can be 5…) added items instead of after each item add.
One more thing
I discovered that when I use this technique inside of the Loaded event handler of a Windows, it’s content was staying white until the long-running job stops. To make it work, I started the job in the ContentChanged method to be sure the content is rendered once first. Notice that it’s necessary only when you need to execute a long-running job on the UI-thread.
protected override void
OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
Dispatcher.BeginInvoke(new Action(MyLongProcessing), null);
}
That’s all for today, feel free to add comments


