简体   繁体   English

WPF Dispatcher.InvokeAsync()与异步委托的奇怪行为

[英]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: 然后使用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) 您将获得的输出将是:(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): 如果使用Dispatcher.BeginInvoke()并等待Completed事件,则效果将是相同的(预期):

        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. 我们在这里看到的是,DoAsync()方法中的await使Dispatcher相信操作已结束。

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. 我不是在寻求解决方法。

It is a bug in your code, the object returned from Application.Current.Dispatcher.InvokeAsync(DoAsync); 这是您代码中的错误,该错误是从Application.Current.Dispatcher.InvokeAsync(DoAsync);返回的对象Application.Current.Dispatcher.InvokeAsync(DoAsync); is a Task<Task> , you only await the outer task, not waiting for the inner task to complete. Task<Task> ,您仅等待外部任务,而不等待内部任务完成。 These situations is what .Unwrap() is for. 这些情况就是.Unwrap()的用途。

    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) 您将获得的输出将是:(1)(1.1)(1.2)(1.3)(2)

What Unwrap is doing is effectively turning your code in to Unwrap所做的就是有效地将您的代码

    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 " 有关文档,请参阅“ 如何:解开嵌套任务

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM