Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about dispatcher and async

I'm making a windows 8.1 tablet app and am using the async keyword quite heavily. My understanding of the async keyword is that, while it appears to be synchronous to the programmer, there is no guarantee that you will be running on the same thread when your await finishes.

In my code behind file I have the use of the Dispatcher to run any UI updates on the UI thread. Every example I've found indicates this to be good practice when using a 'callback' type scenario but I've seen no mention of it when using async. From my understanding of async, it would appear as though I'd need to use the dispatcher whenever I want to update the UI after any await call.

I've tried to be clearer by putting my understanding in code below.

private void SomeEventHandler(object sender, RoutedEventArgs e)
{
    UpdateUI(); //This should run in my UI thread
    await Foo(); //When Foo returns I have no guarantee that I am in the same thread
    UpdateUI(); //This could potentially give me an error
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        UpdateUI(); //This will run in the UI thread
    });
}

Do I just need access to the UIContext and the thread doesn't matter? It would be great if someone could clarify this for me.

like image 616
Jacob Duval Avatar asked Feb 12 '23 22:02

Jacob Duval


1 Answers

My understanding of the async keyword is that, while it appears to be synchronous to the programmer, there is no guarantee that you will be running on the same thread when your await finishes.

Not exactly... If the thread that starts the async operation has a synchronization context (which is true for the UI thread), execution will always resume on the same thread, unless you explicitly specified not to capture the synchronization context with .ConfigureAwait(false).

If there is no synchronization context, or if it wasn't captured, then execution will resume on a ThreadPool thread (except if the awaited task actually completes synchronously, in which case you stay on the same thread).

So, here's your code snippet with updated comments:

private void SomeEventHandler(object sender, RoutedEventArgs e)
{
    UpdateUI(); //This should run in my UI thread
    await Foo(); //When Foo returns I am still in the UI thread
    UpdateUI(); //This will work fine, as I'm still in the UI thread

    // This is useless, since I'm already in the UI thread ;-)
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        UpdateUI(); //This will run in the UI thread
    });
}
like image 112
Thomas Levesque Avatar answered Feb 16 '23 03:02

Thomas Levesque