Tuesday, December 9, 2008

Asynchronous Programming and Power Threading

Many of us who've had experience with asynchronous development know how difficult such code can be to write. Asynchronous code is typically non-linear, and jumps from one portion of a program to another. It is difficult to debug, and is difficult to tame if errors occur.
To understand the difficulties inherent in asynchronous development it helps to first consider a simple example.

Suppose you begin an IO operation of some kind, perhaps the download of a large file. The download is going to take several minutes. To avoid locking up your program during the download, you set up a thread on which the operation can run. You start the thread, call it from your main thread, and set up a callback method which can be executed when the operation completes. Because the download is run on a secondary thread, the main thread of your program is still responsive during the download, and can interact with the user. When the task completes, the callback is executed, thereby announcing the termination of the download. You might then have a new asynchronous task that you might want to begin, such as processing the downloaded file and adding portions of its content to a database. Again, this task is going to take some time, and so you start another thread, providing another callback method that can be executed when the task is completed.

The model outlined in the previous paragraph is common, but awkward. The problems inherent in this scenario are numerous, but two of the worst problems can be summed up as follows:

1) The code does not execute in serial fashion, but instead jumps from one callback to another, thereby making it difficult to debug. Someone new to the code might find it hard to understand which callback will execute next, or which thread is currently active.

2) If something goes wrong during the execution of the code, it can be very difficult to clean up the current operation and exit the process smoothly. Operations are occurring on multiple threads, or inside some seemingly random callback. Allocations, open files, and initialized variables are hard to clean up, and it is difficult to define which code should execute next after you enter an error condition.

Setting up a try..catch block is difficult at best, and sometimes impossible. The result can be a mass of spaghetti code that is difficult for the original developer to understand, and nearly incomprehensible to others who are assigned the unfortunate task of maintaining it.
All of these problems are commonly encountered by developers who create asynchronous code.

Jeffrey Richter has written a library that allows us to write asynchronous code in a synchronous style, as if each operation were occurring in a linear, or serial, sequence. In other words, you can write a single method in which the file is first downloaded, then parsed, and data is then inserted in a database. The code looks like synchronous code, and appears to execute in a linear fashion. Behind the scenes, however, the code is actually asynchronous, and uses multiple threads.

The library is built around C# Iterators, which bear the weight of handling the multiple threads that are spawned during your asynchronous operations.

Take a look at the movie to learn exactly how it works, and then download free library to try it yourself. Not only does he show a simple way to write asynchronous code, but he also does a great job of explaining exactly how C# Iterators are put together.

Download or view the video: http://channel9.msdn.com/posts/Charles/Jeffrey-Richter-and-his-AsyncEnumerator/

The library is available at: http://wintellect.com/PowerThreading.aspx