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
Difference between the TPL & async/await (Thread handling)
提问by coding4fun
Trying to understanding the difference between the TPL & async
/await
when it comes to thread creation.
试图了解 TPL & async
/await
在线程创建方面的区别。
I believe the TPL (TaskFactory.StartNew
) works similar to ThreadPool.QueueUserWorkItem
in that it queues up work on a thread in the thread pool. That's of course unless you use TaskCreationOptions.LongRunning
which creates a new thread.
我相信 TPL ( TaskFactory.StartNew
) 的工作原理类似于ThreadPool.QueueUserWorkItem
它在线程池中的线程上排队工作。当然,除非您使用TaskCreationOptions.LongRunning
which 创建一个新线程。
I thought async
/await
would 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
/await
only "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 FromCurrentSynchronizationContext
always 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,因为它在线程池中的线程上排队工作。
差不多。
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.Run
method 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.ReadAsync
will actually create a Task
wrapper around an IOCP (if the Stream
has 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
/await
is 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 Task
can be await
ed - it doesn't have to be an async
method. So Task.Delay
and I/O-bound operations just use TaskCompletionSource
to 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 Task
awaiter will schedule the remainder of the async
method on the current SynchronizationContext
if 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
在当前调度方法的其余部分;否则它继续当前。这在今天不是那么重要,但在不久的将来,这将是一个重要的区别。SynchronizationContext
TaskScheduler
I wrote my own async
/await
introon my blog, and Stephen Toub recently posted an excellent async
/await
FAQ.
我在我的博客上写了我自己的async
/await
介绍,Stephen Toub 最近发布了一篇很棒的async
/await
常见问题解答。
Regarding "concurrency" vs "multithreading", see this related SO question. I would say async
enables concurrency, which may or may not be multithreaded. It's easy to use await Task.WhenAll
or await Task.WhenAny
to do concurrent processing, and unless you explicitly use the thread pool (e.g., Task.Run
or 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.WhenAll
或await Task.WhenAny
进行并发处理,除非您明确使用线程池(例如,Task.Run
或ConfigureAwait(false)
),否则您可以同时进行多个并发操作(例如,多个 I/O 或其他类型,例如Delay
)-他们不需要线程。对于这种情况,我使用术语“单线程并发”,尽管在 ASP.NET 主机中,您实际上最终会得到“零线程并发”。这很甜蜜。
回答by Nicholas Butler
async / await basically simplifies the ContinueWith
methods ( 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();