为什么下面的例子不起作用(两个文本同时更改(:
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.Delay
?await Task.Delay
和Task.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
委托。 就适当的解决方案而言,我强烈建议避免在代码中使用所有async
lambda。Task.Run
确实了解如何处理Task
返回方法,但是通过构建代码,您仍然会让很多事情变得更加困难,特别是您没有利用async
方法捕获同步上下文的事实,因此您不必首先手动将代码封送到 UI 线程。
您可以将答案重写为:
await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Delay(2000);
textnew2.Text = "BackgroundTask";
如果您有一些长时间运行的非 UI CPU 绑定工作要做,并且在完成后要进行 UI 更新,而不是将while 的东西放在带有调度程序调用的Task.Run
lambda 中,只需使用Task.Run
专门调用非 UI CPU 绑定的工作,然后在等待后执行需要在 UI 上下文中运行的任何操作:
await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Run(() => SomeBackroundWork());
textnew2.Text = "BackgroundTask";