Directory
Anonymous methods and lambda expressions
foreach statement
Iterators
Asynchronous programming
I have always praised the advantages of the asynchronous programming model (APM), emphasizing that asynchronous execution of I/O-intensive operations is the key to producing highly responsive and scalable applications and components. These goals can be achieved because APM allows you to do a lot of work with a very small number of threads without having to block any threads. Unfortunately, using APM to build a typical application or component is somewhat difficult, so many programmers are unwilling to do so.
There are several factors that make APM difficult to implement. First, you need to avoid state data residing on the thread's stack, because the data on the thread stack cannot be migrated to other threads. Avoiding stack based data means that method parameters and local variables must be avoided. Over the years, developers have preferred parameters and local variables because they make programming much simpler.
Second, you need to split the code into several callback methods, sometimes called "continued." For example, if you start an asynchronous read or write operation in one method, you must then implement another method that you want to invoke (possibly through a different thread) to handle the results of the I/O operation. But programmers are not used to considering data processing in this way. Migrating state between methods and threads means that the state must be packaged to complicate the implementation process.
Again, many useful programming constructs-such as try/catch/finally statements, lock statements, using statements, even loops (for, while, and foreach statements)-cannot be split between multiple methods. Avoiding these constructs also increases the complexity of the implementation process.
Finally, you try to provide a variety of features, such as reconciling the results of multiple overlapping operations, canceling, timing out, and using UI control modifications to marshal a GUI thread in a Windows® form or a Windows presentation Foundation (WPF) application that uses APM Adds more complexity.
In this installment, I'll demonstrate some of the most recent additions to the C # programming language, which greatly simplifies the use of the asynchronous programming model. Then I'll introduce my own class, called AsyncEnumerator, built on these C # language features to solve the problem I just mentioned. My AsyncEnumerator class makes it easy and fun to use APM in your code. With this class, your code becomes scalable and highly responsive, so there's no reason not to use asynchronous programming. Note that the AsyncEnumerator class is part of the Power Threading library and relies on other code that is also part of the library, which readers can download from wintellect.com.
Anonymous methods and lambda expressions
Figure 1, the Synchronouspattern method shows how to open and read a file synchronously. The method is simple and straightforward; it constructs a FileStream object, assigns byte[], invokes Read, and then processes the returned data. The C # using statement ensures that the FileStream object is closed when data processing is completed.