Asynchronous ShowDialog

It is quite common that in our application we use Modal Windows. Now more and more the asynchronous programming model is used pervasively. C# and VB.Net languages even provides a syntactic sugar for them using the async/await feature.

It is desirable that one could expect to await the ShowDialog unfortunately, ShowDialog is a synchronous API. By definition, synchronous API can’t be await ed; It doesn’t makes sense either trying to await a synchronous method.

However, you can make the synchronous method “awaitable” by wrapping it in a Task — you do it using Task.Run or Task.Factory.StartNew. That executes the given method asynchronously in ThreadPool thread making a synchronous operation asynchronous.

Sounds great right, So it is just a matter of  wrapping ShowDialog call in Task.Run to make it asynchronous. Let’s do that.

Your synchronous code below

Becomes this

Alright, We’re done right? Yes, except that it won’t work –we’re done with it.

This could work for any other synchronous method, but not for anything which is related to UI. UI elements typically have “Thread affinity”. Which means they have to be dealt with the thread which it was created. Otherwise, You’ll get an InvalidOperationException well known as “cross thread exception”.

In this case we could move the creation of window inside the Task.Run(with some trick) and fix the violation of thread affinity requirement. But that will not yield you what you would expect. Window will not be shown as Modal window of the owner. etc.

It turns out that we can’t show the UI in worker thread(at least gracefully). It is evident that we must call the ShowDialog method from the user interface thread only. But the method being synchronous, preventing us from awaiting it. Are we back to the place where we started? No way around it?

Well, we can satisfy the requirement of calling the method in user interface thread itself and asynchronously also. Thanks to Dispatcher.BeginInvoke which makes it possible.

That is a different API which isn’t awaitable; nevertheless msft gifted us the TaskCompletionSource<T> type which could wrap anything in Task.

With just two more lines of code, it is possible

We could make this code as a reusable piece of code. Maybe a nice extension method as below

Then you could call it as

Note that the code is about Wpf, but it doesn’t matter much. You can pretty much do the same in any UI technology with very little change. For example, in winforms, you’d use Form instead of Window, DialogResult instead of bool?  and Control.BeginInvoke method instead of Dispatcher.BeginInvoke.

That’s about it. Hope you enjoyed the post. Let’s make everything asynchronous :). Have fun.