Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Dispatcher.InvokeAsync() strange behavior with async delegate

If you have an async method, like the one below:

    private async Task DoAsync()
    {
        Console.WriteLine(@"(1.1)");
        Thread.Sleep(200);
        Console.WriteLine(@"(1.2)");
        await Task.Delay(1000);
        Console.WriteLine(@"(1.3)");
    }

and you call it asynchronously with Dispatcher:

        Console.WriteLine(@"(1)");
        await Application.Current.Dispatcher.InvokeAsync(DoAsync);
        Console.WriteLine(@"(2)");

The output you'll get will be: (1) (1.1) (1.2) (2) (1.3)

If you use Dispatcher.BeginInvoke() and you'll wait for Completed event, the effect will be the same (which is expected):

        Console.WriteLine(@"(1)");
        var dispatcherOp = Dispatcher.BeginInvoke(new Func<Task>(DoAsync));
        dispatcherOp.Completed += (s, args) =>
        {               
        Console.WriteLine(@"(2)");
        };

What we see here is that the await in DoAsync() method makes Dispatcher believe the operation ended.

My question: is it a bug or a feature? Do you know any document that describes this behavior? I couldn't find anything.

I'm not asking for a workaround.

like image 696
Maciek Świszczowski Avatar asked Dec 18 '22 01:12

Maciek Świszczowski


1 Answers

It is a bug in your code, the object returned from Application.Current.Dispatcher.InvokeAsync(DoAsync); is a Task<Task>, you only await the outer task, not waiting for the inner task to complete. These situations is what .Unwrap() is for.

    Console.WriteLine(@"(1)");
    await Application.Current.Dispatcher.InvokeAsync(DoAsync).Unwrap();
    Console.WriteLine(@"(2)");

The output you will get will be: (1) (1.1) (1.2) (1.3) (2)

What Unwrap is doing is effectively turning your code in to

    Console.WriteLine(@"(1)");
    await (await Application.Current.Dispatcher.InvokeAsync(DoAsync));
    Console.WriteLine(@"(2)");

But with a nicer looking format.

For documentation see "How to: Unwrap a nested task"

like image 199
Scott Chamberlain Avatar answered Dec 28 '22 23:12

Scott Chamberlain