套接字编程中的APM、EAP和TPL

10
我发现了这篇关于异步API的问题:Difference between […]Async and Begin[…] .net asynchronous APIs,但是这个回答让我有点困惑。
在谈到这些模式时,Stephen说:
大多数*Async方法(带有相应的*Completed事件)使用基于事件的异步模式。旧的(但仍然完全有效的)Begin *和End *是一种称为异步编程模型的模式。
Socket类是一个例外;其*Async方法没有任何对应的事件;它本质上只是APM的一种方式,以避免过多的内存分配。
我理解为使用*Async方法更有效率,至少在涉及sockets时如此。 但是他之后提到了Task Parallel Library:
然而,APM和EBAP都将被一种基于Task Parallel Library的更加灵活的方法所取代。由于TPL可以轻松包装APMs,旧类可能不会直接更新;扩展方法用于为旧的APM方法提供Task等效项。
我在MSDN上找到了TPL and Traditional .NET Asynchronous Programming,我了解TPL的基础知识,如创建任务、取消、连续性等,但我仍然无法理解这些问题:
相比之下,异步编程模型(APM)和基于事件的异步模式(EAP)各有什么优势?TPL如何轻松地包装APM意味着APM和EAP都被TPL取代了?
最重要的是:在socket编程中应该使用哪种方法;
1. APM? 2. EAP? 3. 通过Task包装的APM或EAP? 4. 使用Socket类的阻塞方法在任务中使用TPL? 5. 其他?

将async socket在高性能应用程序中变为并行而非仅并发。 - user2165473
2个回答

7
TPL如何轻松地包装APM,这是否意味着TPL正在取代APM和EAP?
并不是。新API中是否用TAP(任务异步模式)替换APM和EAP与此无关。我期望出于多种原因,TAP将取代APM和EAP。对我而言,其中主要原因是使用TAP编写的代码更易组合。即使不考虑您可以传递以确定继续是否运行的选项到ContinueWith中,执行“。ContinueWith(/ *...* /)。ContinueWith(/ *...* /)”通常比通过Begin / End方法链接异步调用所需编写的相应代码更易读。 TPL还为任务提供了各种组合器,例如WaitAll和WaitAny,可以使某些场景变得更加容易。通过async / await关键字在C#和VB.NET中提供的语言支持将使这一点变得更加容易。
能够在TAP中包装APM使切换到此模式变得更容易,因为这意味着您无需重写现有代码以使其适应新模型。
在套接字编程中应该使用哪个?
我建议在Socket上使用TAP包装APM方法。除非您能证明将Begin / End方法包装成任务的额外开销是可扩展/足够快的差异,否则我会利用TAP的易编码性。

5
Gideon提供了一个很好的答案,我想提供更多背景信息:
APM更常见,并且有一个相当严格定义的模式。例如,TPL具有用于APM方法的通用包装器(TaskFactory.FromAsync),但是它无法对EAP执行相同操作,因为EAP没有那么严格的定义。
EAP有一个巨大的优势:事件回调为您处理线程编组。因此,它们非常适合UI的基本后台操作(BackgroundWorker)等。
TAP结合了两者的优点:默认情况下自动线程编组和严格定义的公共模式。它还具有异步操作的良好对象表示形式(任务)。
“TPL可以轻松包装APM”如何意味着“APM和EAP都正在被TPL替换”?
它并不是这样的。
“然而,APM和EBAP都将被基于任务并行库的一种更加灵活的方法所取代。”- 意思是新代码不需要包括APM / EAP方法/事件;新代码应该使用TAP方法。
“由于TPL可以轻松包装APM,因此旧类可能不会直接更新;扩展方法用于为旧的APM方法提供任务等效项。”- 意思是您可以使用TaskFactory.FromAsync将TAP方法添加到现有的APM类型中;我认为TPL团队会采用这种方法,而不是修改BCL中的大量类。但是,出于性能原因,BCL / TPL团队审查了整个框架,并直接向.NET类添加了TAP方法,而不是使用扩展方法。新的TAP方法已包含在即将推出的.NET 4.5中...

2
TAP本身不执行线程封送,但是与await结合使用时会执行。 - svick
2
我认为这取决于“TAP”的定义。我将asyncawait包含在TAP中。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接