Free mag vol1 | Page 784

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING Time is: 6:51:51 PM Time is: 6:51:52 PM Press any key to continue . . . If you did want to send in some information for use by the delegate target, simply substitute the null value of the second constructor parameter with the appropriate information, like so: // Establish timer settings. Timer t = new Timer(timeCB, "Hello From Main", 0, 1000); You can then obtain the incoming data as follows: static void PrintTime(object state) { Console.WriteLine("Time is: {0}, Param is: {1}", DateTime.Now.ToLongTimeString(), state.ToString()); }  Source Code The TimerApp project is included under the Chapter 19 subdirectory. Understanding the CLR ThreadPool The next thread-centric topic you will examine in this chapter is the role of the CLR thread pool. When you invoke a method asynchronously using delegate types (via the BeginInvoke() method), the CLR does not literally create a brand-new thread. For purposes of efficiency, a delegate’s BeginInvoke() method leverages a pool of worker threads that is maintained by the runtime. To allow you to interact with this pool of waiting threads, the System.Threading namespace provides the ThreadPool class type. If you would like to queue a method call for processing by a worker thread in the pool, you can make use of the ThreadPool.QueueUserWorkItem() method. This method has been overloaded to allow you to specify an optional System.Object for custom state data in addition to an instance of the WaitCallback delegate. public static class ThreadPool { ... public static bool QueueUserWorkItem(WaitCallback callBack); public static bool QueueUserWorkItem(WaitCallback callBack, object state); } The WaitCallback delegate can point to any method that takes a System.Object as its sole parameter (which represents the optional state data) and returns nothing. Do note that if you do not provide a System.Object when calling QueueUserWorkItem(), the CLR automatically passes a null value. To illustrate queuing methods for use by the CLR thread pool, ponder the following program, which makes use of the Printer type once again. In this case, however, you are not manually creating an array of Thread objects; rather, you are assigning members of the pool to the PrintNumbers() method. 729