为什么以下示例不起作用(两个文本同时更改):
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()
之间有什么区别?
答案 0 :(得分:3)
您有一个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()
被点击后认为任务已完成。
答案 1 :(得分:1)
正如Scott's Answer正确解释的那样,即使您正在等待延迟,您的异步版本仍在继续的原因是因为Displatcher.RunAsync
接受void
委托。至于适当的解决方案,我强烈建议避免在代码中使用所有async
lambdas。 Task.Run
确实理解如何处理Task
返回方法,但是你仍然通过构建代码来使自己做很多事情,特别是你没有利用这个事实async
方法捕获同步上下文,这样您就不必首先将代码手动编组到UI线程。
您可以将答案重写为:
await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Delay(2000);
textnew2.Text = "BackgroundTask";
如果您有一些长期运行的非UI CPU绑定工作要做,并且要完成UI更新,而不是将 while thing 放在带有调度程序的Task.Run
lambda中整个调用只需使用Task.Run
来专门调用非UI CPU绑定的工作,然后在等待它之后做任何需要在UI上下文中运行的内容:
await Task.Delay(2000);
textnew1.Text = "Dispatched";
await Task.Run(() => SomeBackroundWork());
textnew2.Text = "BackgroundTask";