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.WhenAllawait Task.WhenAny做并发处理,除非你明确使用线程池(例如, Task.RunConfigureAwait(false) ),那么你可以有多个并发操作进行中同时(例如,多个I / O或其他types,如Delay ) – 并没有他们所需要的线程。 我在这种场景中使用术语“单线程并发”,但是在ASP.NET主机中,实际上可能会以“ 线程并发”结束。 这很漂亮。

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

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

所以,C#5版本将是:

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