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

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

BeginInvoke and EndInvoke

Before we look at examples of these asynchronous programming patterns, let’s take a closer look at the BeginInvoke and EndInvoke methods. Some of the important things to know about BeginInvoke are the following:

When calling BeginInvoke, the actual parameters in the parameter list consist of the following:

The parameters required by the referenced method

Two additional parameters, called the callback parameter and the state parameter

BeginInvoke retrieves a thread from the thread pool and starts the referenced method running on the new thread.

BeginInvoke returns to the calling thread a reference to an object implementing the IAsyncResult interface. This interface reference contains information about the current state of the asynchronous method. The initial thread then continues execution.

The following code shows an example of calling a delegate’s BeginInvoke method. The first line declares a delegate type called MyDel. The next line declares a method called Sum, which matches the delegate.

The following line declares a delegate object called del, of the delegate type MyDel, and initializes its invocation list with the Sum method.

Finally, the last line of code calls the BeginInvoke method of the delegate object and supplies it with the two delegate parameters 3 and 5 and the two BeginInvoke parameters callback and state, which are set to null in this example. When executed, the BeginInvoke method performs two actions:

It gets a thread from the thread pool and starts method Sum running on the new thread, supplying it with 3 and 5 as its actual parameters.

It collects information about the state of the new thread and makes it available through a reference to an interface of type IAsyncResult, which it returns to the calling thread. The calling thread, in this example, stores it in a variable called iar.

delegate long MyDel( int first, int second ); // Delegate declaration

 

 

...

 

 

 

 

 

 

 

 

 

static long Sum(int x, int y){ ... }

// Method matching delegate

 

 

...

 

 

 

 

 

 

 

 

 

MyDel del = new MyDel(Sum);

 

 

 

// Create delegate object

 

 

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

 

 

 

 

 

 

 

 

Information about

Invoke delegate

Delegate

Extra

 

 

new thread

asynchronously

params

params

614

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

You use the EndInvoke method to retrieve the values returned by the asynchronous method call and to release resources used by the thread. EndInvoke has the following characteristics:

It takes as a parameter the reference to the IAsyncResult returned by the BeginInvoke method and finds the thread it refers to.

If the thread pool thread has exited, EndInvoke does the following:

It cleans up the exited thread’s loose ends and disposes of its resources.

It finds the value returned by the referenced method and returns that value as its return value.

If the thread pool thread is still running when EndInvoke is called, the calling thread stops and waits for it to finish before cleaning up and returning the value. Because EndInvoke cleans up after the spawned thread, you must make sure that an EndInvoke is called for each BeginInvoke.

If the asynchronous method triggers an exception, the exception is raised when EndInvoke is called.

The following line of code shows an example of calling EndInvoke to retrieve the value from an asynchronous method. You must always include the reference to the IAsyncResult object as a parameter.

Delegate object

long result = del.EndInvoke( iar );

Return value

IAsyncResult

from async method

object

EndInvoke supplies all the output from the asynchronous method call, including ref and out parameters. If a delegate’s referenced method has ref or out parameters, they must be included in EndInvoke’s parameter list before the reference to the IAsyncResult object, as shown here:

long result = del.EndInvoke(out someInt, iar);

Return value

Out

IAsyncResult

from async method

parameter

object

615

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

The Wait-Until-Done Pattern

Now that you understand the BeginInvoke and EndInvoke delegate methods, we can look at the asynchronous programming patterns. The first one we’ll look at is the wait-until-done pattern. In this pattern, the initial thread initiates an asynchronous method call, does some additional processing, and then stops and waits until the spawned thread finishes. It’s summarized as follows:

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

//Do additional work in the calling thread, while the method

//is being executed asynchronously in the spawned thread.

...

long result = del.EndInvoke( iar );

The following code shows a full example of this pattern. This code uses the Sleep method of the Thread class to suspend itself for 100 milliseconds (1/10 of a second). The Thread class is in the

System.Threading namespace.

using System;

 

 

 

using System.Threading;

 

 

// For Thread.Sleep()

delegate long MyDel( int

first, int second );

// Declare delegate type

class Program {

 

 

 

 

static long Sum(int x, int y)

 

// Declare method for async

{

 

 

 

 

Console.WriteLine("

 

Inside Sum");

 

Thread.Sleep(100);

 

 

 

 

return x + y;

 

 

 

}

 

 

 

 

static void Main( ) {

 

 

 

 

MyDel del = new MyDel(Sum);

 

 

 

Console.WriteLine(

"Before BeginInvoke" );

 

IAsyncResult iar =

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

 

Console.WriteLine(

"After

BeginInvoke" );

 

Console.WriteLine(

"Doing stuff" );

 

 

long result = del.EndInvoke( iar );

// Wait for end and get result

 

Console.WriteLine(

"After

EndInvoke: {0}", result );

}

 

 

 

}

 

 

 

 

This code produces the following output:

Before BeginInvoke

After BeginInvoke

Doing stuff

Inside Sum

After EndInvoke: 8

616

CHAPTER 22 INTRODUCTION TO ASYNCHRONOUS PROGRAMMING

The AsyncResult Class

Now that you’ve seen BeginInvoke and EndInvoke in action in their simplest forms, it’s time to take a closer look at IAsyncResult, which is an integral part of using these methods.

BeginInvoke returns a reference to an IAsyncResult interface that is inside a class object of type AsyncResult. The AsyncResult class represents the state of the asynchronous method. Figure 22-6 shows a representation of some of the important parts of the class. The important things to know about the class are the following:

When you call a delegate object’s BeginInvoke method, the system creates an object of the class AsyncResult. It doesn’t, however, return a reference to the class object. Instead, it returns a reference to the interface contained in the object—IAsyncResult.

An AsyncResult object contains a property called AsyncDelegate, which returns a reference to the delegate that was invoked to start the asynchronous method. This property, however, is part of the class object but not part of the interface.

The IsCompleted property returns a Boolean value indicating whether the asynchronous method has completed.

The AsyncState property returns a reference to the object that was listed as the state parameter in the BeginInvoke method invocation. It returns a reference of type object. I'll explain this in the section on the callback pattern.

Figure 22-6. An AsyncResult class object

617

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