What\'s actually difference between Asynchronous Programming Model and Event-based Asychronous Pattern?
Which approach to use and when
From the client code POV:
EAP: You set up an event handler for an event whose name ends in "Completed" then call a method whose name ends with "Async". You can sometimes call a method with "Cancel" in its name that might cancel it.
APM: You call a method whose name starts with "Begin" then poll its result or recieve a callback, then call a method that starts with "End".
As far as I know of the two, APM is implemented across most of the BCL IO classes and WCF, mainly lower level uncancellable operations (as in to cancel you just ignore the result). EAP is found on more higher level classes i.e. to download a file, where there are multiple steps and some kind of meaningful cancellation behaviour.
So if you need to choose which to implement (and you are deliberately limiting yourself to these two) I guess its down to what you are doing is cancellable or not.
From the client code POV you don't always get a choice. Its probably best to use C# 4.5 Tasks if you can, they can work with any of the older async mechanisms via wrappers.
A comprehensive answer is given at MSDN article "Deciding When to Implement the Event-based Asynchronous Pattern".
The main idea of this article (and short answer to your question) sounds like "Generate the event-based pattern by default, with an option to generate the IAsyncResult pattern"
The Asynchronous Programming Model (APM) is the model you see with BeginMethod(...)
and EndMethod(...)
pairs.
For example here is a Socket
using the APM implementation:
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);
}
}
The Event-based Asynchronous Pattern (EAP) is the model you see with MethodAsync(...)
and CancelAsync(...)
pairs. There's usually a Completed
event. BackgroundWorker
is a good example of this pattern.
As of C# 4.5, both have been replaced by the async/await
pattern, which is using the Task Parallelism Library (TPL). You will see them marked with Async
after the method name and usually returning an awaitable Task
or Task<TResult>
. If you are able to target .NET 4.5, you should definitely use this pattern over the APM or EAP design.
For example, compressing a (potentially large) file asynchronously:
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();
}
}