异步编程模型和基于事件的异步模式之间有什么区别?
使用哪种方法以及何时使用?
答案 0 :(得分:19)
异步编程模型( 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
标记,并且通常会返回等待 Task
或Task<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();
}
}
答案 1 :(得分:5)
从客户端代码POV:
EAP:您为名称以“已完成”结尾的事件设置事件处理程序,然后调用名称以“Async”结尾的方法。您有时可以在名称中使用“取消”调用可能取消它的方法。
APM:您调用名称以“Begin”开头的方法然后轮询其结果或接收回调,然后调用以“End”开头的方法。
据我所知,APM是在大多数BCL IO类和WCF中实现的,主要是较低级别的不可撤销操作(如取消你只是忽略结果)。 EAP可以在更高级别的类上找到,即下载文件,其中有多个步骤和某种有意义的取消行为。
因此,如果您需要选择实施哪些(并且您故意将自己限制在这两个范围内),我认为您正在做的事情是可以取消的。
从客户端代码POV中,您并不总能做出选择。如果可以,最好使用C#4.5任务,他们可以通过包装器使用任何旧的异步机制。
答案 2 :(得分:2)
MSDN文章"Deciding When to Implement the Event-based Asynchronous Pattern"给出了一个全面的答案。
本文的主要思想(以及对您的问题的简短回答)听起来像“默认情况下生成基于事件的模式,并提供生成IAsyncResult模式的选项”