也许我误解了一些东西,但我一直认为,默认情况下,当等待一个不完整的任务时,当前的“上下文”被捕获并用于在任务完成时恢复该方法。但我发现这是错误的行为(至少对我而言):
private static Task StartTask()
{
return Task.Run(() =>
{
Debug.WriteLine("StartTask thread id = " + Thread.CurrentThread.ManagedThreadId);
});
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
await Task.Run(async () =>
{
Debug.WriteLine("Thread id before await task = " + Thread.CurrentThread.ManagedThreadId);
await StartTask().ConfigureAwait(true);
Debug.WriteLine("Thread id after await task = " + Thread.CurrentThread.ManagedThreadId);
});
}
我在调试输出中收到了这样的结果
Thread id before await task = 12
StartTask thread id = 13
Thread id after await task = 13
为什么代码执行上下文在等待后会发生变化?
答案 0 :(得分:4)
默认情况下,当等待未完成的任务时,捕获当前的“上下文”并用于在任务完成时恢复该方法
这是对的。您观察到的行为是正确的。
问题是:捕获的“背景”是什么?这是当前的SynchronizationContext
,除非是null
,在这种情况下,它是当前的TaskScheduler
。
当Task.Run
执行您的委托时,它正在线程池上执行它。因此,目前没有SynchronizationContext
。所以使用了当前的TaskScheduler
;请注意,由于实际上没有执行任务(委托直接在线程池上执行),因此当前TaskScheduler
是默认的TaskScheduler
,表示线程池。