【发布时间】:2013-12-17 15:47:10
【问题描述】:
如果我需要将代码执行推迟到 UI 线程消息循环的未来迭代之后,我可以这样做:
await Task.Factory.StartNew(
() => {
MessageBox.Show("Hello!");
},
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
这将类似于await Task.Yield(); MessageBox.Show("Hello!");,此外,如果我愿意,我可以选择取消任务。
在使用默认同步上下文的情况下,我可以类似地使用await Task.Run 在池线程上继续。
事实上,比起Task.Yield,我更喜欢Task.Factory.StartNew 和Task.Run,因为它们都明确定义了延续代码的范围。
那么,await Task.Yield() 在什么情况下真正有用?
【问题讨论】:
-
我只在单元测试中使用了
Task.Yield和to work around an obscure ASP.NET issue where anasyncmethod must not complete synchronously。 -
我知道你的问题没有问这个,但它有点相关。如果在您的窗口没有焦点时执行该代码,则调用
MessageBox.Show()而不传递IWin32Window ownerargument 可能会导致消息框“弹出”您的窗口。如果在 GUI 线程上完成,这尤其令人困惑。此外,如果您确实将IWin32Window传递给MessageBox.Show(),则需要在UI 线程上这样做。因此,在这种情况下,您不得使用Task.Run(),并且必须将TaskScheduler传递给StartNew()。 -
此外,没有必要将
MessageBox.Show()放在单独的线程上,因为MessageBox.Show()泵送消息队列并运行计划到GUI 的SynchronizationContext的延续。即,即使在显示MessageBox.Show()时,您也可以像往常一样继续更新表单并显示async方法。
标签: c# .net task-parallel-library async-await