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