multithreading TPL 和 async/await 之间的区别(线程处理)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10285159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:18:53  来源:igfitidea点击:

Difference between the TPL & async/await (Thread handling)

multithreadingtask-parallel-libraryasync-awaitc#-5.0

提问by coding4fun

Trying to understanding the difference between the TPL & async/awaitwhen it comes to thread creation.

试图了解 TPL & async/await在线程创建方面的区别。

I believe the TPL (TaskFactory.StartNew) works similar to ThreadPool.QueueUserWorkItemin that it queues up work on a thread in the thread pool. That's of course unless you use TaskCreationOptions.LongRunningwhich creates a new thread.

我相信 TPL ( TaskFactory.StartNew) 的工作原理类似于ThreadPool.QueueUserWorkItem它在线程池中的线程上排队工作。当然,除非您使用TaskCreationOptions.LongRunningwhich 创建一个新线程。

I thought async/awaitwould work similarly so essentially:

我认为async/await本质上会类似地工作:

TPL:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith( 
    (antecedent) => {
        DoSomeWorkAfter(); 
    },TaskScheduler.FromCurrentSynchronizationContext());

Async/Await:

Async/ Await:

await DoSomeAsyncWork();  
DoSomeWorkAfter();

would be identical. From what I've been reading it seems like async/awaitonly "sometimes" creates a new thread. So when does it create a new thread and when doesn't it create a new thread? If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise I would think it would have to. I guess my understanding of FromCurrentSynchronizationContextalways was a bit fuzzy also. I always throught it was, in essence, the UI thread.

将是相同的。从我一直在阅读的内容来看,似乎async/await只有“有时”会创建一个新线程。那么它什么时候创建一个新线程,什么时候不创建一个新线程呢?如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须创建。我想我对FromCurrentSynchronizationContext一直的理解也有点模糊。我一直认为它本质上是 UI 线程。

回答by Stephen Cleary

I believe the TPL (TaskFactory.Startnew) works similar to ThreadPool.QueueUserWorkItem in that it queues up work on a thread in the thread pool.

我相信 TPL (TaskFactory.Startnew) 的工作原理类似于 ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作。

Pretty much.

差不多

From what i've been reading it seems like async/await only "sometimes" creates a new thread.

从我一直在阅读的内容来看,似乎 async/await 只有“有时”会创建一个新线程。

Actually, it never does. If you want multithreading, you have to implement it yourself. There's a new Task.Runmethod that is just shorthand for Task.Factory.StartNew, and it's probably the most common way of starting a task on the thread pool.

实际上,它永远不会。如果你想要多线程,你必须自己实现。有一种新Task.Run方法只是 的简写Task.Factory.StartNew,它可能是在线程池上启动任务的最常见方式。

If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise i would think it would have to.

如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须创建。

Bingo. So methods like Stream.ReadAsyncwill actually create a Taskwrapper around an IOCP (if the Streamhas an IOCP).

答对了。所以像这样的方法Stream.ReadAsync实际上会Task在 IOCP 周围创建一个包装器(如果Stream有一个 IOCP)。

You can also create some non-I/O, non-CPU "tasks". A simple example is Task.Delay, which returns a task that completes after some time period.

您还可以创建一些非 I/O、非 CPU 的“任务”。一个简单的例子是Task.Delay,它返回一个在一段时间后完成的任务。

The cool thing about async/awaitis that you can queue some work to the thread pool (e.g., Task.Run), do some I/O-bound operation (e.g., Stream.ReadAsync), and do some other operation (e.g., Task.Delay)... and they're all tasks! They can be awaited or used in combinations like Task.WhenAll.

async/很酷的一点await是,您可以将一些工作排​​入线程池(例如,Task.Run),执行一些 I/O 绑定操作(例如,Stream.ReadAsync),并执行一些其他操作(例如,Task.Delay)......所有任务!它们可以等待或组合使用,例如Task.WhenAll.

Any method that returns Taskcan be awaited - it doesn't have to be an asyncmethod. So Task.Delayand I/O-bound operations just use TaskCompletionSourceto create and complete a task - the only thing being done on the thread pool is the actual task completion when the event occurs (timeout, I/O completion, etc).

任何返回的方法都Task可以被await编辑——它不必是一个async方法。因此Task.Delay,I/O 绑定操作仅用于TaskCompletionSource创建和完成任务——线程池上唯一要做的是事件发生时的实际任务完成(超时、I/O 完成等)。

I guess my understanding of FromCurrentSynchronizationContext always was a bit fuzzy also. I always throught it was, in essence, the UI thread.

我想我对 FromCurrentSynchronizationContext 的理解也总是有点模糊。我一直认为它本质上是 UI 线程。

I wrote an articleon SynchronizationContext. Most of the time, SynchronizationContext.Current:

我写了一篇关于SynchronizationContext. 大多数时候,SynchronizationContext.Current

  • is a UI context if the current thread is a UI thread.
  • is an ASP.NET request context if the current thread is servicing an ASP.NET request.
  • is a thread pool context otherwise.
  • 如果当前线程是 UI 线程,则是 UI 上下文。
  • 如果当前线程正在为 ASP.NET 请求提供服务,则为 ASP.NET 请求上下文。
  • 否则是线程池上下文。

Any thread canset its own SynchronizationContext, so there are exceptions to the rules above.

任何线程都可以设置自己的SynchronizationContext,因此上述规则有例外。

Note that the default Taskawaiter will schedule the remainder of the asyncmethod on the current SynchronizationContextif it is not null; otherwise it goes on the current TaskScheduler. This isn't so important today, but in the near future it will be an important distinction.

请注意,如果默认Task等待器不为 null,则默认等待器将async在当前调度方法的其余部分;否则它继续当前。这在今天不是那么重要,但在不久的将来,这将是一个重要的区别。SynchronizationContextTaskScheduler

I wrote my own async/awaitintroon my blog, and Stephen Toub recently posted an excellent async/awaitFAQ.

我在我的博客上写了我自己的async/await介绍,Stephen Toub 最近发布了一篇很棒的async/await常见问题解答

Regarding "concurrency" vs "multithreading", see this related SO question. I would say asyncenables concurrency, which may or may not be multithreaded. It's easy to use await Task.WhenAllor await Task.WhenAnyto do concurrent processing, and unless you explicitly use the thread pool (e.g., Task.Runor ConfigureAwait(false)), then you can have multiple concurrent operations in progress at the same time (e.g., multiple I/O or other types like Delay) - and there is no thread needed for them. I use the term "single-threaded concurrency" for this kind of scenario, though in an ASP.NET host, you can actually end up with "zero-threaded concurrency". Which is pretty sweet.

关于“并发”与“多线程”,请参阅此相关 SO 问题。我会说async启用并发性,它可能是也可能不是多线程的。它易于使用await Task.WhenAllawait Task.WhenAny进行并发处理,除非您明确使用线程池(例如,Task.RunConfigureAwait(false)),否则您可以同时进行多个并发操作(例如,多个 I/O 或其他类型,例如Delay)-他们不需要线程。对于这种情况,我使用术语“单线程并发”,尽管在 ASP.NET 主机中,您实际上最终会得到“线程并发”。这很甜蜜。

回答by Nicholas Butler

async / await basically simplifies the ContinueWithmethods ( Continuations in Continuation Passing Style)

async / await 基本上简化了ContinueWith方法( Continuations in Continuation Passing Style

It does not introduce concurrency - you still have to do that yourself ( or use the Async version of a framework method. )

它不会引入并发性 - 您仍然必须自己做(或使用框架方法的异步版本。)

So, the C# 5 version would be:

因此,C# 5 版本将是:

await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();