Free mag vol1 | Page 761

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING  Note The callback method will be called on the secondary thread, not the primary thread. This has important implications when using threads within a graphical user interface (WPF or Windows Forms) as controls have thread-affinity, meaning they can be manipulated only by the thread that created them. You’ll see some examples of working the threads from a GUI later in this chapter, during the examination of the Task Parallel Library (TPL) and the new .NET 4.5 C# async and await keywords. Like any delegate, AsyncCallback can invoke methods that match only a specific pattern, which in this case is a method taking IAsyncResult as the sole parameter and returning nothing: // Targets of AsyncCallback must match the following pattern. void MyAsyncCallbackMethod(IAsyncResult itfAR) Assume you have another Console Application (AsyncCallbackDelegate) making use of the BinaryOp delegate. This time, however, you will not poll the delegate to determine whether the Add() method has completed. Rather, you will define a static method named AddComplete() to receive the notification that the asynchronous invocation is finished. Also, this example makes use of a class-level static bool field, which will be used to keep the primary thread in Main() running a task until the secondary thread is finished.  Note The use of this Boolean variable in this example is, strictly speaking, not thread safe, as there are two different threads which have access to its value. This will be permissible for the current example; however, as a very good rule of thumb, you must ensure data that can be shared among multiple threads is locked down. You’ll see how to do so later in this chapter. namespace AsyncCallbackDelegate { public delegate int BinaryOp(int x, int y); class Program { private static bool isDone = false; static void Main(string[] args) { Console.WriteLine("***** AsyncCallbackDelegate Example *****"); Console.WriteLine("Main() invoked on thread {0}.", Thread.CurrentThread.ManagedThreadId); BinaryOp b = new BinaryOp(Add); IAsyncResult iftAR = b.BeginInvoke(10, 10, 706