C# 异步编程APM与EAP

C# 异步编程APM与EAP,c#,.net,asynchronous,C#,.net,Asynchronous,异步编程模型和基于事件的异步模式之间的实际区别是什么 使用哪种方法以及何时使用?异步编程模型(APM)就是您在BeginMethod(…)和EndMethod(…)对中看到的模型 例如,这里有一个使用APM实现的套接字: var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // ... socket.Begin

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

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

异步编程模型(APM)就是您在
BeginMethod(…)
EndMethod(…)
对中看到的模型

例如,这里有一个使用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);
   }
 }
基于事件的异步模式(EAP)是您使用
MethodAsync(…)
CancelAsync(…)
对看到的模型。通常会有一个
已完成的
事件
BackgroundWorker
就是这种模式的一个很好的例子

从C#4.5开始,两者都被
async/await
模式所取代,该模式使用任务并行库(TPL)。您将看到它们在方法名称后标记为
Async
,通常返回一个可等待的
任务
任务
。如果您能够以.NET4.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:为名称以“Completed”结尾的事件设置事件处理程序,然后调用名称以“Async”结尾的方法。有时,您可以调用名称中带有“Cancel”的方法,该方法可能会取消它

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

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

因此,如果您需要选择实现哪一个(并且您故意将自己限制在这两个范围内),我想这取决于您正在做的事情是否可以取消


从客户机代码的角度来看,您并不总是可以选择。如果可以,最好使用C#4.5任务,它们可以通过包装器与任何较旧的异步机制一起工作。

MSDN文章给出了一个全面的答案


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

文章很好地涵盖了这一点。很棒的文章!肯定添加到了我的书签收藏中。关于APM设计中缺少取消功能的一点很好。同样如前所述,
Task.Factory.fromsync(…)
是将APM风格转变为TPL模式的C#4.5包装器。请参阅:“title=”TPL和传统的.NET异步编程“>很抱歉,这里有这么多的注释(为什么他们大多数“支持的”链接格式在注释中不起作用)?