套接字编程的APM,EAP和TPL

时间:2012-07-02 14:41:08

标签: c# sockets design-patterns asynchronous task-parallel-library

我发现Difference between […]Async and Begin[…] .net asynchronous APIs问题,但this answer让我感到困惑。

谈到这些模式,斯蒂芬说:

  

大多数*异步方法(具有相应的*已完成事件)正在使用基于事件的异步模式。较旧(但仍然完全有效)的Begin *和End *是一种称为异步编程模型的模式。

     

Socket类是此规则的一个例外;它的*异步方法没有任何相应的事件;它本质上只是以避免过多内存分配的方式完成APM。

我认为使用* Async方法更有效率,至少在套接字方面。 但后来他提到了任务并行库:

  

然而,APM和EBAP都被基于任务并行库的更灵活的方法所取代。由于TPL可以轻松地包装APM,因此较旧的类可能不会直接更新;扩展方法用于为旧的APM方法提供Task等价物。

我在MSDN上找到TPL and Traditional .NET Asynchronous Programming,我知道TPL的基础知识,创建任务,取消,延续等等,但我仍然无法理解这些:

异步编程模型(APM)和基于事件的异步模式(EAP)相互比较有什么优势? TPL如何轻松包装APM 意味着APM和EAP都被替换为 TPL?

最重要的是:我应该在套接字编程中使用哪个;

  • APM?
  • EAP?
  • 由任务包裹的APM或EAP?
  • TPL在任务中使用Socket类的阻塞方法吗?
  • 其他?

2 个答案:

答案 0 :(得分:7)

  

TPL如何轻松包装APM意味着APM和EAP都被TPL取代?

没有。更新的APM和EAP将被替换为TAP(任务异步模式),或者在新的API中没有与此无关。我希望TAP能够以各种原因取代APM和EAP。我的主要原因是你为使用TAP编写的代码组成得更好。执行.ContinueWith(/* ... */).ContinueWith(/* ... */)通常比通过Begin / End方法编写链异步调用所需的相应代码读取得更好,即使您没有考虑可以传递给ContinueWith以确定是否继续的选项应该跑。 TPL还为任务提供了各种组合器,例如WaitAllWaitAny,这些组合可以使某些场景更容易。通过async / await关键字进入C#和VB.NET的语言支持将使这更容易。

能够在TAP中包装APM使得更容易切换到这种模式,因为这意味着您不必重写现有代码以使其适合新模型。

  

我应该在套接字编程中使用哪个?

我建议在Socket上使用TAP包装APM方法。除非您能够证明将Begin / End方法包装到Task中的额外开销是可扩展/足够快的差异,否则我将利用TAP编码的简易性。

答案 1 :(得分:4)

基登有一个很好的答案;我只想提供更多背景资料:

  

异步编程模型(APM)和基于事件的异步模式(EAP)相互比较有什么优势?

APM更常见,它有一个非常严格定义的模式。例如,TPL具有APM方法的通用包装器(TaskFactory.FromAsync),但它不能对EAP执行相同的操作,因为EAP不是严格定义的。

EAP有一个很大的优势:事件回调为您处理线程编组。因此,它们非常适合用于UI的基本后台操作(BackgroundWorker)。

TAP结合了两者的优点:默认情况下自动线程编组和严格定义的常见模式。它还具有异步操作的良好对象表示(Task)。

  

“TPL如何轻松包装APM”意味着“APM和EAP都将被TPL取代”?

没有。

“然而,APM和EBAP正在被基于任务并行库的更灵活的方法所取代。” - 意味着新代码不需要包含APM / EAP方法/事件;新代码应该包括TAP方法。

“由于TPL可以轻松地包装APM,因此较旧的类可能不会直接更新;扩展方法用于为旧的APM方法提供任务等价物。” - 意味着您可以使用TaskFactory.FromAsync将TAP方法添加到现有APM类型;我认为TPL团队会采用这种方法而不是修改BCL中的大量类。 但是,我在这个猜想中错了。出于性能原因,BCL / TPL团队确实审查了整个框架,并将TAP方法直接添加到.NET类中,而不是使用扩展方法。新的TAP方法包含在.NET 4.5中,即将推出......