Design Patterns‎ > ‎

Asynchronous Programming Model

The ability to use asynchronous operations is a key building block for scalable and responsive applications. Synchronous operations block the thread of execution until the operation is complete, rendering the thread unusable for other tasks during that time. Asynchronous operations on the other hand return immediately and send some form of notification at a later time that the operation completed (or failed). This frees the calling thread up to do useful things, for example handle user interaction.Thus, most I/O related classes in the .NET base class library (BCL) support asynchronous operations.

The asynchronous programming pattern (APM) works as follows.For every operation you have two methods. BeginOperationstarts the operation. It takes the operations parameters and a callback method as input. The callback is invoked when the operation completes or fails. The callback receives an instance of IAsyncResult as parameter. This is a moniker for the operations result. By passing the it to the EndOperationmethod the result can be retrieved. It throws an exception if the operation failed.

While this enables us to use asynchronous operations, it has some major drawbacks. The logic is now split over various callbacks. This makes the code hard to read and maintain. There is no clear semantic on which thread calls the callback. It may for example be a thread from the default thread pool or even the thread that called BeginOperation. This is error prone as it is now easy to deadlock yourself or starve the thread pool. Also, coordination between multiple asynchronous operations is rather complex.