Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
20
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать
// Empty statement

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

The Polling Pattern

In the polling pattern, the initial thread initiates an asynchronous method call, does some additional processing, and then uses the IsCompleted method of the IAsyncResult object to check periodically whether the spawned thread has completed. If the asynchronous method has completed, the initial thread calls EndInvoke and continues. Otherwise, it does some additional processing and checks again later. The “processing” in this example just consists of counting from 0 to 10,000,000.

delegate long MyDel(int first, int second);

class Program

 

{

 

 

static long Sum(int x, int y)

 

{

 

 

Console.WriteLine("

Inside Sum");

Thread.Sleep(100);

 

return x + y;

 

}

 

 

static void Main()

 

{

 

Spawn async method

MyDel del = new MyDel(Sum);

 

 

IAsyncResult iar = del.BeginInvoke(3, 5, null, null); // Start async.

Console.WriteLine("After BeginInvoke");

Check whether the async method is done.

while ( !iar.IsCompleted )

{

Console.WriteLine("Not Done");

// Continue processing, even though in this case it's just busywork. for (long i = 0; i < 10000000; i++)

;

}

Console.WriteLine("Done");

Call EndInvoke to get result and clean up.

long result = del.EndInvoke(iar); Console.WriteLine("Result: {0}", result);

}

}

618

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

This code produces the following output:

After BeginInvoke

Not Done

Inside Sum

Not Done

Not Done

Done

Result: 8

619

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

The Callback Pattern

In the previous two patterns, wait-until-done and polling, the initial thread continues with its flow of control only after it knows that the spawned thread has completed. It then retrieves the results and continues.

The callback pattern is different in that once the initial thread spawns the asynchronous method, it goes on its way without synchronizing with it again. When the asynchronous method call completes, the system invokes a user-supplied method to handle its results and to call the delegate’s EndInvoke method. This user-defined method is called a callback method, or just a callback.

The two extra parameters at the end of the BeginInvoke parameter list are used with the callback method as follows:

The first of the two parameters, the callback parameter, is the name of the callback method.

The second parameter, the state parameter, can be either null or a reference to an object you want passed into the callback method. You’ll be able to access this object through the method’s

IAsyncResult parameter using its AsyncState property. The type of this parameter is object.

The Callback Method

The signature and return type of the callback method must be of the form described by the AsyncCallback delegate type. This form requires that the method take a single parameter of type IAsyncResult and have a void return type, as shown here:

void AsyncCallback( IAsyncResult iar )

There are several ways you can supply the callback method to the BeginInvoke method. Since the callback parameter in BeginInvoke is a delegate of type AsyncCallback, you can supply it as a delegate, as shown in the first code statement that follows. Or you can just supply the name of the callback method and let the compiler create the delegate for you. Both forms are semantically equivalent.

Create a delegate with the callback method.

IAsyncResult iar1 =

del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone), null);

Just use the callback method’s name.

IAsyncResult iar2 = del.BeginInvoke(3, 5, CallWhenDone, null);

The second BeginInvoke parameter is used to send an object to the callback method. It can be an object of any type, but the parameter is of type object, so inside the callback method you’ll have to cast it to the correct type.

620

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

Calling EndInvoke Inside the Callback Method

Inside the callback method, your code should call the delegate’s EndInvoke method and take care of handling the output results of the asynchronous method execution. To call the delegate’s EndInvoke method, though, you need a reference to the delegate object, which is in the initial thread—not here in the spawned thread.

If you’re not using BeginInvoke’s state parameter for anything else, you can use it to send the delegate reference to the callback method, as shown here:

Delegate object

Send delegate object as state param

IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, del);

Otherwise, you can extract the delegate’s reference from the IAsyncResult object sent into the method as the parameter. This is shown in the following code and illustrated in Figure 22-7.

The single parameter to the callback method is a reference to the IAsyncResult interface of the asynchronous method that has just completed. Remember that the IAsyncResult interface object is inside the AsyncResult class object.

Although the IAsyncResult interface doesn’t have a reference to the delegate object, the AsyncResult class object enclosing it does have a reference to the delegate object. So, the first line inside the example method body gets a reference to the class object by casting the interface reference to the class type. Variable ar now has a reference to the class object.

With the reference to the class object, you can now use the AsyncDelegate property of the class object and cast it to the appropriate delegate type. This gives you the delegate reference, which you can then use to call EndInvoke.

using System.Runtime.Remoting.Messaging;

// Contains AsyncResult class

void CallWhenDone( IAsyncResult iar )

 

{

AsyncResult ar = (AsyncResult) iar;

// Get class object reference

 

 

MyDel del = (MyDel) ar.AsyncDelegate;

// Get reference to delegate

 

long Sum = del.EndInvoke( iar );

// Call EndInvoke

...

 

}

 

 

621

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

Figure 22-7. Extracting the delegate’s reference inside the callback method

622

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

The following code puts it all together and is an example of using the callback pattern.

using System;

 

using

System.Runtime.Remoting.Messaging;

// To access the AsyncResult type

using

System.Threading;

 

delegate long MyDel(int first, int second);

class Program

 

{

 

static long Sum(int x, int y)

 

{

 

Console.WriteLine("

Inside Sum");

Thread.Sleep(100);

 

return x + y;

 

}

 

static void CallWhenDone(IAsyncResult iar)

{

 

Console.WriteLine("

Inside CallWhenDone.");

AsyncResult ar = (AsyncResult) iar;

MyDel del = (MyDel)ar.AsyncDelegate;

long result = del.EndInvoke(iar);

Console.WriteLine

 

("

The result is: {0}.", result);

}

 

static void Main()

{

MyDel del = new MyDel(Sum);

Console.WriteLine("Before BeginInvoke"); IAsyncResult iar =

del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone), null);

Console.WriteLine("Doing more work in Main."); Thread.Sleep(500);

Console.WriteLine("Done with Main. Exiting.");

}

}

This code produces the following output:

Before BeginInvoke

Doing more work in Main.

Inside Sum

Inside CallWhenDone.

The result is: 8.

Done with Main. Exiting.

623

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]