繁体   English   中英

等待创建另一个线程吗?

[英]Does await create another thread?

我阅读了有关异步并等待的Microsoft文档 它说:

async和await关键字不会导致创建其他线程。

但是我运行下面的代码

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        static void Main()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Task task = Test();
            task.Wait();
        }

        public async static Task Test()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        }

    }
}

结果是

1个
1个
4

很明显,

await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

在另一个线程中运行。 为什么文档说没有创建线程?

我已经阅读了上一个问题,使用async / await是否会创建一个新线程? ,但它不能回答我的问题,那里的答案只是从Microsoft来源复制粘贴。 为什么在测试中看到不同的线程ID?

我总是鼓励人们阅读我的async介绍 ,并跟进async最佳实践 综上所述:

默认情况下, await捕获“上下文”,并在该上下文中继续执行async方法。 在这种情况下,上下文是线程池上下文。 因此,这就是为什么您看到Test恢复在线程池线程上执行的原因。

asyncawait本身不会创建任何其他线程; 例如,如果您在UI应用程序中执行相同的操作,则“上下文”将是UI线程,而Test将继续在该UI线程上执行。 但是由await隐式捕获的上下文负责调度asnc连续,并且在此示例中,上下文只是将其调度到线程池。

您在测试中看到了不同的线程ID,因为使用了不同的线程来执行代码。 这并不意味着异步/等待导致了其他线程的创建。 在这种情况下,使用的线程已经存在于称为线程池的线程池中。

有两个不同的想法:

  • 代表要完成的工作的任务, 以及
  • 如何实际处理任务(例如计划和执行)

Async / await与前者有关,但是您的测试代码告诉您有关后者的信息:处理这些任务的特定机制。

该机制由上下文决定。 一些上下文使用多个线程(但是请注意,上下文取决于它如何管理这些线程,包括是否以及何时创建新线程),但某些上下文仅使用1个线程。

使用了多个线程是与上下文有关的,而不是异步/等待。

我改变了你的例子:

public async static Task Test()
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    await Task.CompletedTask; // <--- instead of Task.Delay()
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

现在输出为1、1、1。

await未创建新线程。 Task.Delay是元凶!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM