Anda di halaman 1dari 5

C# Delegates and Events—Asynchronous method calls at C# Online.NET (CSharp-O...

Page 1 of 5

C# Delegates and Events—Asynchronous method


calls
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp)
Developer Training, Visual Studio

#
C
a
n
d
A
fS
V
S
E
N
T.N
P
T
E
l-isR
C
A
d
n
P e
h
jrp
w o
/u
b
mctvya
d
n

sA
d
yG
b
e
lg
o

CSharp-Online.NET:Articles
Asynchronous method calls C# Articles

Another useful feature of delegates is the ability to execute a method C# Delegates and Events
asynchronously. That is, through a delegate, you can begin invocation of a ■ Delegates
method and then return immediately while the delegate executes its method in ■ Multicast delegates
a separate thread. ■ Thread delegates
■ Anonymous methods
The following example demonstrates the use of delegates for asynchronous ■ Asynch method calls
method invocation. To see this in action we need a method that simulates a ■ Events
■ Win32 callbacks
lengthy operation, such as flushing data to disk. Below is a class named ■ Conclusion
DataCache, which may periodically need to write its cache to a file. The
class contains a method named FlushToDisk to simulate this operation. edit

class DataCache {
public int FlushToDisk(string fileName) {
// simulate a long operation
Thread.Sleep(4000);
return 0;
}
}

Since writing to disk is an expensive operation, we would like execute the FlushToDisk method
asynchronously. The next example defines the CacheFlusher delegate and then uses it to call the
DataCache object’s FlushToDisk method asynchronously.

class Program {
// define a delegate for the long operation
delegate int CacheFlusher(string fileName);

static void Main(string[] args) {


// create the object and then the delegate
DataCache cache = new DataCache();
CacheFlusher flusher = new CacheFlusher(cache.FlushToDisk);

// invoke the method asynchronously


IAsyncResult result = flusher.BeginInvoke("data.dat", null, null);

// get the result of that asynchronous operation


int retValue = flusher.EndInvoke(result);

Console.WriteLine(retValue);
}
}

In the first asynchronous example, the Main method creates an instance of DataCache and encapsulates its
FlushToDisk method in an instance of the CacheFlusher delegate. At the time our CacheFlusher

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronou... 12/10/2008
C# Delegates and Events—Asynchronous method calls at C# Online.NET (CSharp-O... Page 2 of 5

delegate is declared, the compiler generates two methods for it named BeginInvoke and EndInvoke.
These two methods, respectively, are used to kick off a lengthy method call and then retrieve its return value
when that method is finished. Rather than invoking the delegate as before, Main executes the delegate as an
asynchronous operation by calling its BeginInvoke method.

The generated BeginInvoke method will accept the same argument types as declared in the delegate’s
signature, followed by some other arguments that we will ignore for now. The return value of
BeginInvoke is a reference to an interface named IAsyncResult which we later pass to EndInvoke
to receive the return value of the asynchronous method.

The generated EndInvoke method is defined to return the same type as the asynchronous method. When
called, EndInvoke will block until the asynchronous method completes its execution. Therefore, to be
efficient, we need to find other strategies for calling EndInvoke that will not block the calling thread.
Below, I show three techniques for calling EndInvoke, polling for completion, using a wait handle, and
using an AsyncCallback delegate.

First we look at polling. The next code segment uses a while loop to poll the IsCompleted property of
the IAsyncResult object. If the method call is not yet complete, then we can perform some other work and
check during the next pass through the loop to see if the asynchronous operation has completed.

// begin execution asynchronously


IAsyncResult result = flusher.BeginInvoke("data.dat", null, null);

// wait for it to complete


while (result.IsCompleted == false) {
// do some work
Thread.Sleep(10);
}

// get the return value


int returnValue = flusher.EndInvoke(result);

The next technique is to block on the IAsyncResult object’s wait handle. When the asynchronous method
is complete, the IAsyncResult object’s AsyncWaitHandle will be signaled. Then any thread waiting
on that handle will be awakened. Once awake, the thread can call the IAsyncResult object’s EndInvoke
method to receive the return value.

// call the delegate asynchronously


IAsyncResult result =
flusher.BeginInvoke("data.dat", null, null);

// wait for the call to finish


result.AsyncWaitHandle.WaitOne();

// get the return value


int returnValue = flusher.EndInvoke(result);

The final method is to create an instance of the AsyncCallback delegate and pass it to the BeginInvoke
method. The AsyncCallback delegate is defined in the System namespace. It accepts an
IAsyncResult reference as its only parameter and returns void.

When you pass an AsyncCallback to BeginInvoke, the delegate will invoke that callback upon
completion of the asynchronous operation. Then, you can use that opportunity to call EndInvoke to retrieve
the return value and perform any resource cleanup, as the next example shows.

static void Main(string[] args) {


// create the object
DataCache cache = new DataCache();

// create the delegate

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronou... 12/10/2008
C# Delegates and Events—Asynchronous method calls at C# Online.NET (CSharp-O... Page 3 of 5

CacheFlusher flusher = new CacheFlusher(cache.FlushToDisk);

// call the delegate asynchronously


flusher.BeginInvoke("data.dat", new AsyncCallback(CallbackMethod), flusher);

// wait to exit
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}

static void CallbackMethod(IAsyncResult result) {


// get the delegate that was used to call that
// method
CacheFlusher flusher =
(CacheFlusher) result.AsyncState;

// get the return value from that method call


int returnValue = flusher.EndInvoke(result);

Console.WriteLine("The result was " + returnValue);


}

If you run this example you will see that the line “Press Enter to Exit” will be displayed in the
console window, followed by the output from CallbackMethod. This is because the Main method calls
BeginInvoke and continues processing, displaying its own output without waiting for the
CacheFlusher delegate to finish. Later, when the asynchronous operation is complete, the delegate calls
the CallbackMethod, which writes its output to the screen.

The Main method begins by calling the delegate object’s BeginInvoke method as before. But, this time
those second and third arguments are used. The second argument is an instance of another delegate named
AsynchCallback. The AsynchCallback delegate is defined to accept an IAsyncResult reference
and return void, such as the static CallbackMethod provided as part of the example. When the
asynchronous operation is complete, the delegate invokes that callback. It is within the body of that
CallbackMethod, the method referenced by the AsynchCallback, that we have the opportunity to call
EndInvoke.

Whatever object you pass to the third argument of BeginInvoke will be stored in the AsyncState
property of the IAsyncResult reference passed to the CallbackMethod. Notice in the
CallbackMethod that the first thing we do is cast the AsyncState property to the CacheFlusher
delegate. This is so that we can call the object’s EndInvoke method to receive the return value.

Retrieved from "http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%


94Asynchronous_method_calls"

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronou... 12/10/2008
C# Delegates and Events—Asynchronous method calls at C# Online.NET (CSharp-O... Page 4 of 5

o
rivP S
Ju
cyIn
awm
g
sN
lL
e
B1
0
3fW
t$F
C
9
4
.7

Today's Deals: Electronics

d
A
y
b
s
g
o
G
le

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronou... 12/10/2008
C# Delegates and Events—Asynchronous method calls at C# Online.NET (CSharp-O... Page 5 of 5

■ About CSharp-Online.NET
■ Disclaimers
■ Privacy policy
■ © CSharp-Online.NET ? †

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronou... 12/10/2008