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

时间:2012-12-21 16:29:38

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

我很困惑。一个或多个Task如何在一个线程上并行运行?我对并行的理解显然是错误的。

MSDN的比特我无法理解:

  

async和await关键字不会导致其他线程   创建。异步方法不需要多线程,因为异步   方法不会在自己的线程上运行。该方法在当前运行   同步上下文并仅在线程上使用时间   方法有效。

..和:

  

在启动任务和等待任务之间,您可以启动其他任务。   其他任务隐式并行运行,但没有额外的任务   线程已创建。

1 个答案:

答案 0 :(得分:24)

它们不是并行运行,而是轮流运行。当正在运行的任务阻止进度时,它会将其状态和控制权存储到就绪任务中。这是合作的多任务处理,而不是真正的并行性。

线程根据样本原理运行。但是,我想强调几个关键的区别。

首先,仅仅因为async / await不是操作系统线程:

  • 任务不会看到不同的线程ID
  • 当任务产生时,线程本地存储不会自动进行上下文切换。

其次,行为差异:

  • async / await使用协作式多任务处理,Win32线程使用抢占式。因此,有必要使用async / await模型明确控制所有阻塞操作。因此,您可以通过阻止调用未写入的函数来阻止整个线程及其所有任务。
  • 任务不会在多处理系统上并行执行。由于重新引入被控制,这使得保持数据结构更加容易一致。

正如Stephen在评论中指出的那样,如果使用多线程同步上下文,可以在多个OS线程中同时执行(以及所有复杂性和潜在的竞争条件)。但是MSDN的引用是关于单线程上下文的情况。

最后,在其他地方使用了相同的设计范例,通过研究这些范例,您可以了解async / await的良好做法:

  • Win32 Fibers (使用与线程相同的调用样式,但是合作)
  • Win32 重叠I / O 操作,Linux aio
  • 协程