A review of asynchronous programming patterns in .net
In Visual Studio 11, C# and VB.NET will gain new keywords like async and await for asynchronous programming. Before we dive into it, I will first give a brief preview on what we have so far.
IAsyncResult Pattern
IAsyncResult pattern has existed since .net 1.x. The class that implements pattern would implement Beginxxx and Endxxx methods.For example, the WebRequest class has BeginGetResponse and EndGetResponse in additional to synchronous GetResponse method. Here is the signature of the BeginGetResponse method:
public virtual IAsyncResult BeginGetResponse( AsyncCallback callback, Object state )
The caller of the method needs to supply a callback function which will be call when the asynchronous operation is over. The callee will usually create another thread to do the actual operation and immediate an IAsyncResult to the caller. Here are the members of IAsyncResult:
Member | Description |
AsyncState | An optional application-specific object that contains information about the asynchronous operation. |
AsyncWaitHandle | A WaitHandle that can be used to block application execution until the asynchronous operation completes. |
CompletedSynchronously | A value that indicates whether the asynchronous operation completed on the thread used to call BeginOperationName instead of completing on a separate ThreadPool thread. |
IsCompleted | A value that indicates whether the asynchronous operation has completed. |
The caller of Beginxxx method can do one of the following:
- Wait on the AsyncWaitHandle if the caller needs to do processing after the async operation.
- Poll the IsCompleted and AsyncState for completion and possibly the progress.
- Do nothing. Wait for the callback to be called.
- Call the Endxxx method. If it is called before the completion of the async operation, the calling thread will block until the asynchronous operation is complete.
Event-based Asynchronous Pattern
Since .net 2.0, we gain another asynchronous pattern – the Event-based Asynchronous Pattern (EAP). EAP was created to allow a richer event model. The class that implement EAP can raised multiple events during a single asynchronous operation so that the callee does not have to poll the class.
The class that implements EAP uses xxxAsync naming conversion for its asynchronous methods. The class can optionally implements xxxCancelAsync methods or simply a CancelAsync method to allow caller to cancel the asynchronous operation. When a caller calls a xxxAsync method, the method will immediately return. The caller needs to subscribe one of the events exposed by the class for notifications of completion and progress. WebClient and BackgroundWorker are two typical components that use this pattern. For library designers, MSDN has a nice article descripting when to use which pattern.
Task-based Asynchronous Pattern
.Net framework 4.0 introduced yet another way to run asynchronous operation – the Task class in the Task Parallel Library. Although the task parallel library is about parallel execution and is much more than asynchronous programming, the .net framework 4.5 uses it as the base for yet another asynchronous pattern – the Task-based Asynchronous Patterns (TAP). The class that implements TAP would expose xxxAsync methods, just like EAP. However, the xxxAsync methods return Task<TResult>. The callee can then use the members of Task<TResult> to check completion or progress, wait or continue with another operation. This pattern is the basis for the async and await keywords in Visual Studio 11; the methods that support TAP can be marked using the async keywoard and then consumed asynchronously with the await keyword. That is why only methods return Task, Task<TResult> or void (that is, no results) can be marked with async.
[Edited 5/23/2012]
Found this MSDN Magazine article that discusses these patterns in more detail: http://msdn.microsoft.com/en-us/magazine/ff959203.aspx.