[英]await does not resume context after async operation?
我已经从Noseratio中读到了这个问题 , 该问题显示了一个行为,即在等待完成其操作后, TaskScheduler.Current
不同 。
答案指出:
如果没有执行任何实际任务 ,则
TaskScheduler.Current
与TaskScheduler.Default
相同
这是真的。 我已在这里看到它:
TaskScheduler.Default
- 返回
ThreadPoolTaskScheduler
一个实例TaskScheduler.Current
- 如果从执行任务中调用,则返回当前正在执行的任务的
TaskScheduler
- 如果从任何其他地方调用将返回
TaskScheduler.Default
但转念一想,如果是这样,让我们做创建一个实际的Task
(不只是Task.Yield()
并对其进行测试:
async void button1_Click_1(object sender, EventArgs e)
{
var ts = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(async () =>
{
MessageBox.Show((TaskScheduler.Current == ts).ToString()); //True
await new WebClient().DownloadStringTaskAsync("http://www.google.com");
MessageBox.Show((TaskScheduler.Current == ts).ToString());//False
}, CancellationToken.None, TaskCreationOptions.None,ts).Unwrap();
}
第一个Messagebox是“True”,第二个是“False”
题:
如您所见,我确实创建了一个实际任务。
我可以理解为什么第一个MessageBox产生True
。 多数民众赞成:
如果从执行任务中调用,则返回当前正在执行的任务的TaskScheduler
并且该任务确实具有ts
,即发送的TaskScheduler.FromCurrentSynchronizationContext()
但为什么在第二个 MessageBox中没有保留上下文? 对我来说,斯蒂芬的回答并不清楚。
附加信息 :
如果我写(第二个消息框):
MessageBox.Show((TaskScheduler.Current == TaskScheduler.Default).ToString());
它确实产生了true
。 但为什么 ?
混淆的原因是:
TaskScheduler
。 在UI线程上运行的代码的默认情况是TaskScheduler.Current
存储ThreadPoolTaskScheduler
和SynchronizationContext.Current
存储WindowsFormsSynchronizationContext
(或其他UI应用程序中的相关文件) TaskScheduler.Current
中的ThreadPoolTaskScheduler
并不一定意味着它是用于运行当前代码段的TaskScheduler
。 它还意味着TaskSchdeuler.Current == TaskScheduler.Default
,因此“没有使用TaskScheduler
” 。 TaskScheduler.FromCurrentSynchronizationContext()
不返回“acutal” TaskScheduler
。 它返回一个“代理”,可以将任务直接发布到捕获的SynchronizationContext
。 因此,如果您在开始任务之前(或在任何其他地方)运行测试,您将获得与等待之后相同的结果 :
MessageBox.Show(TaskScheduler.Current == TaskScheduler.FromCurrentSynchronizationContext()); // False
因为TaskScheduler.Current
是ThreadPoolTaskScheduler
而TaskScheduler.FromCurrentSynchronizationContext()
返回SynchronizationContextTaskScheduler
。
这是你的例子的流程:
SynchronizationContextTaskScheduler
从UI的SynchronizationContext
(即WindowsFormsSynchronizationContext
)。 TaskScheduler
上使用Task.Factory.StartNew
计划您创建的任务。 由于它只是一个“代理”,它将委托发布到WindowsFormsSynchronizationContext
,后者在UI线程上调用它。 SynchronizationContextTaskScheduler
相关联。 WindowsFormsSynchronizationContext
时被“挂起”。 WindowsFormsSynchronizationContext
而不是SynchronizationContextTaskScheduler
因为SynchronizationContext
具有优先权( 这可以在Task.SetContinuationForAwait
看到 )。 然后它在UI线程上定期运行,没有任何“特殊” TaskScheduler
因此TaskScheduler.Current == TaskScheduler.Default
。 因此,创建的任务在使用SynchronizationContext
的代理TaskScheduler
上运行,但是在await发布到SynchronizationContext
而不是TaskScheduler
之后的延续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.