异步编程APM与EAP

Lev*_*Lev 21 .net c# asynchronous

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

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

Eri*_*rik 20

异步编程模型(APM),是你看到的模型BeginMethod(...)EndMethod(...)对.

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

 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);
   }
 }
Run Code Online (Sandbox Code Playgroud)

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

C#4.5开始,两者都被async/await模式取代,模式使用任务并行库(TPL).您将看到它们Async在方法名称后标记,并且通常返回等待 TaskTask<TResult>.如果您能够以.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();
  }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*art 5

从客户端代码POV:

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

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

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

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

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

  • 关于__APM__设计缺少取消功能的好处.同样如上所述,`Task.Factory.FromAsync(...)`是用于将__APM__样式转换为__TPL__模式的C#4.5包装器.请参阅:<a rel="nofollow noreferrer" href="http://msdn.microsoft.com/en-us/library/dd997423.aspx" title="TPL和Traditional .NET Asynchronous Programming"> </a> (2认同)