TPL和asynchronous/等待(线程处理)之间的区别
尝试理解TPL和asynchronous/等待线程创build之间的区别。
我相信TPL(TaskFactory.Startnew)类似于ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作。 这当然,除非你使用TaskCreationOptions.LongRunning创build一个新的线程。
我认为asynchronous/等待将同样如此基本:
TPL:
Factory.StartNew( () => DoSomeAsyncWork() ) .ContinueWith( (antecedent) => { DoSomeWorkAfter(); },TaskScheduler.FromCurrentSynchronizationContext());
asynchronous/等待:
await DoSomeAsyncWork(); DoSomeWorkAfter();
将是相同的。 从我一直在读它看起来像asynchronous/只等待“有时”创build一个新的线程。 那么它什么时候创build一个新的线程,什么时候不创build一个新的线程呢? 如果你正在处理IO完成端口,我可以看到它不必创build一个新的线程,否则我会认为它将不得不。 我想我对FromCurrentSynchronizationContext的理解总是有点模糊。 我总是从头到尾都是UI线程。
我相信TPL(TaskFactory.Startnew)的作用类似于ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作。
很多 。
从我一直在读它看起来像asynchronous/只等待“有时”创build一个新的线程。
事实上,它从来没有。 如果你想multithreading,你必须自己实现。 有一个新的Task.Run
方法,它只是Task.Factory.StartNew
简写,它可能是在线程池上启动一个任务的最常见的方式。
如果你正在处理IO完成端口,我可以看到它不必创build一个新的线程,否则我会认为它将不得不。
答对了。 所以像Stream.ReadAsync
这样的方法实际上会创build一个围绕IOCP的Task
包装(如果Stream
有一个IOCP)。
您也可以创build一些非I / O,非CPU“任务”。 一个简单的例子是Task.Delay
,它返回一段时间后完成的任务。
关于async
/ await
的很酷的事情是你可以将一些工作排列到线程池(例如, Task.Run
),做一些I / O绑定操作(例如Stream.ReadAsync
),并执行一些其他的操作(例如, Task.Delay
)…他们都是任务! 他们可以等待或组合使用像Task.WhenAll
。
任何返回Task
方法都可以被await
– 它不一定是一个async
方法。 所以Task.Delay
和I / O绑定操作只是使用TaskCompletionSource
来创build和完成一个任务 – 在线程池上唯一完成的事情是事件发生时的实际任务完成(超时,I / O完成等)。
我想我对FromCurrentSynchronizationContext的理解总是有点模糊。 我总是从头到尾都是UI线程。
我写了一篇关于SynchronizationContext
的文章 。 大部分时间, SynchronizationContext.Current
:
- 是当前线程是UI线程的UI上下文。
- 是当前线程正在处理ASP.NET请求时的ASP.NET请求上下文。
- 否则是一个线程池上下文。
任何线程都可以设置自己的SynchronizationContext
,所以上面的规则也有例外。
请注意,默认的Task
awaiter会在当前的SynchronizationContext
上调度async
方法的其余部分, 如果它不为null ; 否则它将继续当前的TaskScheduler
。 今天不是那么重要,但在不久的将来,这将是一个重要的区别。
我在自己的博客上写了自己的async
/ await
介绍 ,Stephen Toub最近发布了一个非常好的async
/ await
常见问题解答 。
关于“并发”与“multithreading”,请看这个相关的SO问题 。 我会说async
启用并发,可能或可能不是multithreading。 这很容易使用await Task.WhenAll
或await Task.WhenAny
做并发处理,除非你明确使用线程池(例如, Task.Run
或ConfigureAwait(false)
),那么你可以有多个并发操作进行中同时(例如,多个I / O或其他types,如Delay
) – 并没有他们所需要的线程。 我在这种场景中使用术语“单线程并发”,但是在ASP.NET主机中,实际上可能会以“ 零线程并发”结束。 这很漂亮。
async / await基本上简化了ContinueWith
方法(Continuation in Continuation Passing Style )
它不会引入并发性 – 您仍然必须自己做(或者使用框架方法的asynchronous版本)。
所以,C#5版本将是:
await Task.Run( () => DoSomeAsyncWork() ); DoSomeWorkAfter();