Free mag vol1 | Page 764

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING To obtain this data within the scope of AddComplete(), make use of the AsyncState property of the incoming IAsyncResult parameter. Notice that an explicit cast will be required; therefore, the primary and secondary threads must agree on the underlying type returned from AsyncState. static void AddComplete(IAsyncResult itfAR) { ... // Retrieve the informational object and cast it to string. string msg = (string)itfAR.AsyncState; Console.WriteLine(msg); isDone = true; } Here is the output of the final iteration: ***** AsyncCallbackDelegate Example ***** Main() invoked on thread 1. Add() invoked on thread 3. Working.... Working.... Working.... Working.... Working.... AddComplete() invoked on thread 3. Your addition is complete 10 + 10 is 20. Main() thanks you for adding these numbers. Now that you understand how a .NET delegate can be used to automatically spin off a secondary thread of execution to handle an asynchronous method invocation, let’s turn our attention to directly interacting with threads using the System.Threading namespace. Recall that this namespace was the original .NET threading API that shipped since version 1.0.  Source Code The AsyncCallbackDelegate project is located under the Chapter 19 subdirectory. The System.Threading Namespace Under the .NET platform, the System.Threading namespace provides a number of types that enable the direct construction of multithreaded applications. In addition to providing types that allow you to interact with a particular CLR thread, this namespace defines types that allow access to the CLRmaintained thread pool, a simple (non–GUI-based) Timer class, and numerous types used to provide synchronized access to shared resources. Table 19-1 lists some of the important members of this namespace. (Be sure to consult the .NET Framework 4.5 SDK documentation for full details.) 709