简体   繁体   English

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

[英]The async and await keywords don't cause additional threads to be created?

I'm confused. 我糊涂了。 How can one or many Task run in parallel on a single thread? 一个或多个Task如何在一个线程上并行运行? My understanding of parallelism is obviously wrong. 我对并行性的理解显然是错误的。

Bits of MSDN I can't wrap my head around: MSDN的比特我无法理解:

The async and await keywords don't cause additional threads to be created. async和await关键字不会导致创建其他线程。 Async methods don't require multithreading because an async method doesn't run on its own thread. 异步方法不需要多线程,因为异步方法不能在自己的线程上运行。 The method runs on the current synchronization context and uses time on the thread only when the method is active. 该方法在当前同步上下文上运行,并仅在方法处于活动状态时在线程上使用时间。

.. and: ..和:

Between starting a task and awaiting it, you can start other tasks. 在启动任务和等待任务之间,您可以启动其他任务。 The additional tasks implicitly run in parallel, but no additional threads are created. 其他任务隐式并行运行,但不会创建其他线程。

They don't run in parallel, they take turns. 它们并不是并行运行,而是轮流运行。 When progress is blocked for the running Task, it stores its state and yields control to a ready Task. 当正在运行的任务阻止进度时,它会将其状态和控制权存储到就绪任务中。 It's cooperative multitasking, not true parallelism. 这是合作的多任务处理,而不是真正的并行性。

Threads operate on the sample principle. 线程根据样本原理运行。 However there are several key differences I'd like to highlight. 但是,我想强调几个关键的区别。

First, simply because async / await aren't OS threads: 首先,仅仅因为async / await不是OS线程:

  • Tasks won't see different Thread IDs 任务不会看到不同的线程ID
  • Thread-local storage is not automatically context-switched when a Task yields. 当任务产生时,线程本地存储不会自动上下文切换。

Secondly, differences in behavior: 其次,行为的差异:

  • async / await use cooperative multitasking, Win32 threads use pre-emption. async / await使用协作式多任务处理,Win32线程使用抢占式。 So it's necessary that all blocking operations explicitly yield control using the async / await model. 因此,所有阻塞操作必须使用async / await模型明确地产生控制。 So you can end up blocking an entire thread and all its Tasks by making a blocking call to a function not written to yield. 因此,您可以通过对未编写为yield的函数进行阻塞调用来阻止整个线程及其所有任务。
  • Tasks won't be executed in parallel on a multiprocessing system. 任务不会在多处理系统上并行执行。 Since re-entrancy is controlled, this makes keeping data structures consistent a whole lot easier. 由于重新引入被控制,这使得保持数据结构一致性变得更加容易。

As Stephen points out in a comment, you can get simultaneous execution in multiple OS threads (along with all the complexity and potential race conditions) if you use a multithreaded synchronization context. 正如Stephen在评论中指出的那样,如果使用多线程同步上下文,则可以在多个OS线程中同时执行(以及所有复杂性和潜在的竞争条件)。 But the MSDN quotes were about the single-threaded context case. 但是MSDN引用是关于单线程上下文的情况。

Finally, other places this same design paradigm is used, you can learn a lot about good practices for async / await by studying these: 最后,在其他地方使用相同的设计范例,您可以通过研究这些来学习很多关于async / await的良好实践:

  • Win32 Fibers (uses the same call style as threads, but cooperative) Win32 Fibers (使用与线程相同的调用样式,但是合作)
  • Win32 Overlapped I/O operations, Linux aio Win32 重叠I / O操作,Linux aio
  • Coroutines 协同程序

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

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