异步编程APM与EAP

异步编程模型基于事件的 异步模式之间有什么区别?

使用哪种方法以及何时使用?

异步编程模型APM )是您使用BeginMethod(...)EndMethod(...)对看到的模型。

例如,这是一个使用APM实现的Socket

  var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // ... socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, ReceiveCallback, null); void ReceiveCallback(IAsyncResult result) { var bytesReceived = socket.EndReceive(result); if (bytesReceived > 0) { // Handle received data here. } if (socket.Connected) { // Keep receiving more data... socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, ReceiveCallback, null); } } 

基于事件的异步模式EAP )是您使用MethodAsync(...)CancelAsync(...)对看到的模型。 通常会有一个Completed事件。 BackgroundWorker就是这种模式的一个很好的例子。

C#4.5开始 ,两者都被async/await模式取代,后者正在使用任务并行库TPL )。 您将在方法名称后看到它们标记为Async ,并且通常会返回一个等待的 TaskTask 。 如果您能够以.NET 4.5为目标,那么您应该在APM或EAP设计上使用此模式。

例如,异步压缩(可能很大)的文件:

 public static async Task CompressFileAsync(string inputFile, string outputFile) { using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read)) using (var outputStream = File.Create(outputFile)) using (var deflateStream = new DeflateStream(outputStream, CompressionMode.Compress)) { await inputStream.CopyToAsync(deflateStream); deflateStream.Close(); outputStream.Close(); inputStream.Close(); } } 

从客户端代码POV:

EAP:您为名称以“已完成”结尾的事件设置事件处理程序,然后调用名称以“Async”结尾的方法。 您有时可以在名称中使用“取消”调用可能取消它的方法。

APM:您调用名称以“Begin”开头的方法然后轮询其结果或接收回调,然后调用以“End”开头的方法。

据我所知,APM在大多数BCL IO类和WCF中实现,主要是较低级别的不可撤销操作(如取消您只是忽略结果)。 EAP可以在更高级别的类上找到,即下载文件,其中有多个步骤和某种有意义的取消行为。

因此,如果您需要选择实施哪些(并且您故意将自己限制在这两个范围内),我认为您正在做的事情是可取消的。

从客户端代码POV,您并不总是有选择。 如果可以,最好使用C#4.5任务,他们可以通过包装器使用任何旧的异步机制。

MSDN文章“决定何时实现基于事件的异步模式”给出了全面的答案。

本文的主要思想(以及对您的问题的简短回答)听起来像“默认情况下生成基于事件的模式,并提供生成IAsyncResult模式的选项”