await Task vs Task.GetAwaiter



为什么下面的例子不起作用(两个文本同时更改(:

Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
await Task.Delay(2000);
textnew1.Text = "Dispatched";
});
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
{
await Task.Delay(2000);
textnew2.Text = "BackgroundTask";
});
});

这个确实如此(第一个文本更改,第二个文本在两秒钟后更改(:

Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Task.Delay(2000).GetAwaiter().GetResult();
textnew1.Text = "Dispatched";
});
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Task.Delay(2000).GetAwaiter().GetResult();
textnew2.Text = "BackgroundTask";
});
});

为什么在第一个代码中没有等待Task.Delayawait Task.DelayTask.Delay().GetAwaiter().GetResult()有什么区别?

你有一个async void,你的第一个代码示例等效于

Task.Run(async () =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new DispatchedHandler(FirstTask));
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new DispatchedHandler(SecondTask));
});
private async void FirstTask()
{
await Task.Delay(2000);
textnew1.Text = "Dispatched";
}
private async void SecondTask()
{
await Task.Delay(2000);
textnew2.Text = "BackgroundTask";
}

由于 DispatchedHandler 的签名是public delegate void DispatchedHandler()因此您无法返回带有它的任务。当您执行async void时,RunAsync认为一旦命中await Task.Delay(),任务就完成了。

正如 Scott 的答案正确解释的那样,即使您正在等待延迟,您的异步版本仍在继续的原因是因为Displatcher.RunAsync接受void委托。 就适当的解决方案而言,我强烈建议避免在代码中使用所有asynclambda。Task.Run确实了解如何处理Task返回方法,但是通过构建代码,您仍然会让很多事情变得更加困难,特别是您没有利用async方法捕获同步上下文的事实,因此您不必首先手动将代码封送到 UI 线程。

您可以将答案重写为:

await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Delay(2000);
textnew2.Text = "BackgroundTask";

如果您有一些长时间运行的非 UI CPU 绑定工作要做,并且在完成后要进行 UI 更新,而不是将while 的东西放在带有调度程序调用的Task.Runlambda 中,只需使用Task.Run专门调用非 UI CPU 绑定的工作,然后在等待后执行需要在 UI 上下文中运行的任何操作:

await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Run(() => SomeBackroundWork());
textnew2.Text = "BackgroundTask";

最新更新