C# async和await真的是单线程的吗?
我创建了以下代码:C# async和await真的是单线程的吗?,c#,.net,multithreading,async-await,task,C#,.net,Multithreading,Async Await,Task,我创建了以下代码: using System; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main() { Console.WriteLine("M Start"); MyMethodAsync(); Console.WriteLine("M end");
using System;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
Console.WriteLine("M Start");
MyMethodAsync();
Console.WriteLine("M end");
Console.Read();
}
static async Task MyMethodAsync()
{
await Task.Yield();
Task<int> longRunningTask = LongRunningOperationAsync();
Console.WriteLine("M3");
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
static async Task<int> LongRunningOperationAsync()
{
await Task.Delay(1000);
return 1;
}
}
}
这很好,但当我查看线程探查器时,它显示:
然后这个:
然后这个:
所以看起来我产生了线程,但msdn说:
从异步编程到异步和等待:线程
async和await关键字不会导致添加额外的线程
创建。异步方法不需要多线程,因为异步
方法不在自己的线程上运行。该方法在当前服务器上运行
同步上下文,并且仅当
方法处于活动状态。您可以使用Task.Run将CPU绑定的工作移动到
后台线程,但后台线程对进程没有帮助
那只是等待结果出来
我是错过了什么还是不明白?
谢谢
async和await关键字不会导致创建其他线程
对。它将CPU绑定或I/O绑定的工作从进程的线程池移动到另一个线程,这样它就不会在UI线程或当前同步上下文上执行,也不会创建MSDN描述中所指的新线程。我在博客上解释。总之,当await
需要等待异步操作完成时,它将“暂停”当前async
方法,并(默认情况下)捕获“上下文”
异步操作完成后,该“上下文”用于恢复
async
方法。此“上下文”是SynchronizationContext.Current
,除非它是null
,在这种情况下它是TaskScheduler.Current
。在您的例子中,上下文最终成为线程池上下文,因此async
方法的其余部分被发送到线程池。如果从UI线程运行相同的代码,则上下文将是UI上下文,并且所有的async
方法将在UI线程上恢复。它使用线程池中的现有线程,而不是创建一个看起来像Visual Studio中非常漂亮的窗口的线程。很抱歉这个离题的问题,但是哪个版本支持它?用Thread.CurrentThread.ManagedThreadId
装饰您的输出,您可能会看到正在使用3个线程。@GediminasMasait是并行堆栈
和任务
视图,我认为这两个视图都添加到VS 2013中。它们都可以在Debug->Windows
下拉菜单下找到。@DinkarThakur,有点与您的问题相关,但您可能有兴趣阅读Stepen Cleary的博文“”。它深入地观察了当您等待一个基于IO的请求时发生的情况。但如果所有线程都被消耗,那么它将等待。对吗?这是错误的。任务在当前同步上下文上执行。只有在使用基于线程池的同步上下文时,才会使用不同的线程,否则所有操作都是在带有队列的主线程上完成的。阅读“延续传递样式”,这是异步如何在下面工作的。
M Start
M end
M3
1