Wednesday, April 25, 2007

Asynchronous Programming Model - 2.0

I have been reading about the Asynchronous Programming Model in Jeffrey Rithcer's book CLR via C#. I have really enjoyed reading it and i thought of writing something about it.

The Asynchronous Programming Model (APM), as implemented by Delegates, consists of three parts:

- BeginInvoke,
- EndInvoke and
- Rendezvous techniques.

BeginInvoke starts an algorithm, impelmented via a method, on a new thread. EndInvoke retrieves the result of that method. The Rendezvous techniques allow you to determine when the asynchronous operation has completed.

There are three different types of Rendezvous techniques you can use to retrieve the results of an asynchronous delegate invocation

1. Wait Till Completion
2. Polling
3. Method Callback

Wait Till Completion
Wait-Till-Completion is implemented via EndInvoke. Calling this method will block the current thread until the results of the asynchronous method are available. This is the least effective method, because it eliminates all the benefits of APM.
private delegate string StringReturningDelegate();
private void Main()
{
// create an instance of the delegate pointing to a method that takes ten seconds to complete.
StringReturningDelegate fd = new StringReturningDelegate (MethodThatTakes10SecondsToComplete);
// Begin invocation of this delegate
IAsyncResult result = fd.BeginInvoke(null, null);
// Immediately call EndInvoke, which will block for, oh, say, right about ten seconds
string s = fd.EndInvoke(result);
Console.Write(s);
Console.Read();
}
// A method that takes 10 seconds, then returns a string private string.
MethodThatTakes10SecondsToComplete()
{
Thread.Sleep(10000);
return "Done!";
}
Polling
In this technique, you check a property of the IAsyncResult object called IsCompleted. This property will return false until the async operation has completed.

// a delegate for a method that takes no params and returns a string.
private delegate string StringReturningDelegate();
private void Main()
{
// create an instance of the delegate pointing to a method that takes ten seconds to complete
StringReturningDelegate fd = new StringReturningDelegate (MethodThatTakes10SecondsToComplete);
// Begin invocation of this delegate
IAsyncResult receipt = fd.BeginInvoke(null, null);
Console.Write("Working");
// Poll IsCompleted until it returns true; Sleep the current thread between checks to reduce CPU usage
while (!receipt.IsCompleted)
{
Thread.Sleep(500);
// wait half a sec
Console.Write('.');
}
string result = fd.EndInvoke(receipt);
Console.Write(result);
Console.Read();
}
// A method that takes 10 seconds, then returns a string
private string MethodThatTakes10SecondsToComplete()
{
Thread.Sleep(10000);
return "Done!";
}
Method Callback
In this technique, you pass a delegate to the BeginInvoke method that will be called when the asynchronous operation has completed. It will not block your execution, or waste any CPU cycles. This is the most effective emthod of Rendezvous.
//a delegate for a method that takes no params and returns a string.
private delegate string StringReturningDelegate();
private void Main()
{
// create an instance of the delegate pointing to a method that takes ten seconds to complete.
StringReturningDelegate fd = new StringReturningDelegate (MethodThatTakes10SecondsToComplete);
// Begin invocation of this delegate
fd.BeginInvoke(AsyncOpComplete, null);
// Do tons of work here. No, seriously.
Console.Read();
}
/// /// Retrieves the results of MethodThatTakes10SecondsToComplete when called asynchronously/// ///
The IAsyncResult receipt.
private void AsyncOpComplete(IAsyncResult receipt)
{
// Cast to the actual object so that we can access the delegate
AsyncResult result = (AsyncResult)receipt;
// retrieve the calling delegate
StringReturningDelegate gsld = (StringReturningDelegate)result.AsyncDelegate;
// Retrieve our results; this is guaranteed not to block, as the async op is complete
string result = gsld.EndInvoke(receipt);
//write the result to the console
Console.Write(result);
}
// A method that takes 10 seconds, then returns a string
private string MethodThatTakes10SecondsToComplete()
{
Thread.Sleep(10000);
return "Done!";
}

No comments:

Post a Comment