我阅读了Microsoft document有关异步和等待的信息。它说:
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);
在另一个线程中运行。为什么文档说没有创建线程?
我已经阅读了上一个问题Does the use of async/await create a new thread?,但没有回答我的问题,answer只是从Microsoft来源复制粘贴。为什么在测试中看到不同的线程ID?
答案 0 :(得分:8)
我总是鼓励人们阅读我的async
intro,并跟进async
best practices。总结:
await
默认情况下会捕获一个“上下文”,并在该上下文中恢复执行async
方法。在这种情况下,上下文是线程池上下文。因此,这就是为什么您看到Test
恢复在线程池线程上执行的原因。
async
和await
本身不会创建任何其他线程;例如,如果您在UI应用程序中执行相同的操作,则“上下文”将是UI线程,而Test
将继续在该UI线程上执行。但是await
隐式捕获的上下文是调度asnc
连续的原因,在此示例中,上下文只是将其调度到线程池中。
答案 1 :(得分:0)
您在测试中看到了不同的线程ID,因为使用了不同的线程来执行代码。这并不意味着异步/等待导致了其他线程的创建。在这种情况下,使用的线程已经存在于称为线程池的线程池中。
有两个不同的想法:
异步/等待与前者有关,但是您的测试代码告诉您有关后者的信息:处理这些任务的特定机制。
该机制由上下文决定。一些上下文使用多个线程(但是请注意,上下文取决于它如何管理这些线程,包括是否以及何时创建新线程),但某些上下文仅使用1个线程。
使用了一个以上的线程是与上下文有关,而不是异步/等待。
答案 2 :(得分:-2)
我稍微改变了你的例子:
Nothing :: Maybe Integer
现在输出为1、1、1。
public async static Task Test()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await Task.CompletedTask; // <--- instead of Task.Delay()
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
未创建新线程。 await
是元凶!