在等待Task内部后代码的执行上下文

时间:2013-12-02 15:36:47

标签: c# .net multithreading task-parallel-library async-await

也许我误解了一些东西,但我一直认为,默认情况下,当等待一个不完整的任务时,当前的“上下文”被捕获并用于在任务完成时恢复该方法。但我发现这是错误的行为(至少对我而言):

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

为什么代码执行上下文在等待后会发生变化?

1 个答案:

答案 0 :(得分:4)

  

默认情况下,当等待未完成的任务时,捕获当前的“上下文”并用于在任务完成时恢复该方法

这是对的。您观察到的行为是正确的。

问题是:捕获的“背景”是什么?这是当前的SynchronizationContext,除非是null,在这种情况下,它是当前的TaskScheduler

Task.Run执行您的委托时,它正在线程池上执行它。因此,目前没有SynchronizationContext。所以使用了当前的TaskScheduler;请注意,由于实际上没有执行任务(委托直接在线程池上执行),因此当前TaskScheduler是默认的TaskScheduler,表示线程池。