使用async/await时,Task中放在线程池线程上的内容是什么?

3
请看下面的代码:
    public static async Task<int> Answer()
    {
        await Task.Delay(1000);
        return 42;
    }

    static void Main(string[] args)
    {
        for (int j = 0; j < 20; j++)
        {
            Console.WriteLine(j +" " + Thread.CurrentThread.IsThreadPoolThread);
            if (j == 1)
            {
                new Task( async ()=>
                    {
                        int answer = await Answer();
                        Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
                    }).Start();
            }

            Thread.Sleep(200);
        }

        return;

你能猜出打印答案时 CurrentThread.IsThreadPoolThread 的结果是什么吗?

看起来是 Task.Delay(..) 在起作用,因为如果我去掉 await,那么答案就是 False。但是,我似乎在文档中找不到 Delay 实际上将东西放在线程池中的相关信息。

这带我来到更一般的问题。除了 Run(..) 之外,Task 中什么实际上会启动一个线程池线程呢?

编辑:
new Task(...) 替换为 Ask()

    public static async void Ask()
    {
        int answer = await Answer();
        Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
    }

产生相同的结果。
1个回答

3
如我在我的async / await介绍文章中所述,await默认会捕获当前的“上下文”并使用它来执行继续(await后面的代码)。这个“上下文”是SynchronizationContext.Current,除非它为null,此时它就是TaskScheduler.Current

我还在我的博客中描述了在控制台应用程序中使用async。控制台应用程序不提供SynchronizationContext,因此“上下文”回退到TaskScheduler.Current。由于正在执行的Task正在线程池上运行,因此TaskScheduler.CurrentTaskScheduler.Default相同,即线程池任务调度程序。

这就是您的代码在线程池线程上恢复的原因。这是正确的行为。


没有上下文,回调函数是否总是在 TP 线程上运行?这是否也包括 Task.ConfigureAwait(false),即将其设置为 false 将始终在 TP 线程上执行回调函数? - kasperhj
其实,我不确定我完全理解“由于当前正在执行的任务正在线程池上运行”。为什么任务要在线程池上运行? - kasperhj
1
当你使用 new Task ... Start 时没有提供 TaskScheduler,它将在线程池上运行;这与 Task.Run 非常相似。是的,如果你使用 ConfigureAwait(false) 等待一个尚未完成的操作,那么它将始终在线程池上执行后续操作。 - Stephen Cleary
我已经编辑了帖子,将 new Task.Start(..) 替换掉了。结果是一样的。我认为这是因为对 Task.Start(..) 的调用现在是隐式的。结论是通常所有任务都会在没有显式请求的情况下运行在线程池上吗?你觉得有可能让对 Answer(..) 的调用变成阻塞的吗? - kasperhj
1
使用新代码,Answer 将在控制台应用程序的主线程上开始执行,该线程仍然没有 SynchronizationContextTaskScheduler,因此它仍将使用 TaskScheduler.Default。这就是为什么您看到相同的结果,这仍然是正确的原因。没有隐式调用 Task.Start - Stephen Cleary
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接