Recipe18.4.Polling an Asynchronous Delegate


Recipe 18.4. Polling an Asynchronous Delegate

Problem

While an asynchronous delegate is executing, you need to continuously poll it to see whether it has completed. This ability is useful when you need to monitor the length of time it takes the asynchronous delegate to execute. It can also be helpful if you need to monitor other objects in the system in parallel with this asynchronous delegate, possibly to determine which object finishes first, second, third, and so on. It can also be useful when performing a continuous task, such as displaying an indicator to the user that the asynchronous operation is still running.

Solution

Use the IsCompleted property of the IAsyncResult interface to determine when the asynchronous call has completed. Note that the BeginInvoke method call on the delegate passes null for the callback setup parameters. Example 18-3 shows how this is accomplished.

Example 18-3. Polling an asynchronous delegate

 using System; using System.Threading; public class AsyncAction {     public void PollAsyncDelegate( )     {         // Set up the delegate.         AsyncInvoke method1 = TestAsyncInvoke.Method1;         // Since we are not using a callback here, we pass null for the         // callback and null for the object data for the callback.         Console.WriteLine("Calling BeginInvoke on Thread {0}",             Thread.CurrentThread.ManagedThreadId);         IAsyncResult asyncResult = method1.BeginInvoke(null, null);         Console.WriteLine("Starting Polling on Thread {0}",             Thread.CurrentThread.ManagedThreadId);         while (!asyncResult.IsCompleted)         {             // Give up the CPU for 1 second.             Thread.Sleep(1000);             Console.Write('.');         }         Console.WriteLine("Finished Polling on Thread {0}",             Thread.CurrentThread.ManagedThreadId);         try         {             int retVal = method1.EndInvoke(asyncResult);             Console.WriteLine("retVal: " + retVal);         }         catch (Exception e)         {             Console.WriteLine(e.ToString( ));         }     } } 

The following code defines the AsyncInvoke delegate and the asynchronously invoked static method TestAsyncInvoke.Method1:

 public delegate int AsyncInvoke( ); public class TestAsyncInvoke {     public static int Method1( )     {         Console.WriteLine("Invoked Method1 on Thread {0}",             Thread.CurrentThread.ManagedThreadId );         return (1);     } } 

To run the asynchronous invocation, create an instance of the AsyncAction class and call the PollAsyncDelegate method like so:

 AsyncAction aa = new AsyncAction(); aa.PollAsyncDelegate(); 

The output for this code is shown next. Note that the Method1 thread ID is different:

 Calling BeginInvoke on Thread 9 Starting Polling on Thread 9 Invoked Method1 on Thread 10 .Finished Polling on Thread 9 retVal: 1 

Discussion

The delegate, AsyncInvoke, is invoked asynchronously using its BeginInvoke method. The BeginInvoke method returns an IAsyncResult object, which allows access to the result information from an asynchronous operation.

If the delegate accepts a string and an int, in this order, the BeginInvoke method is defined as this:

 public IAsyncResult BeginInvoke(string s, int i, AsyncCallback callback,                                 object state) 

For this recipe, the method that the delegate will call takes no arguments, and the callback and state parameters are set to null. The callback parameter could call back at completion into the code that invoked it, but for this example, it is a no-op.

To poll for the completion of the method1 delegate, you get the IsCompleted property of the IAsyncResult object that is returned by the BeginInvoke method. The IsCompleted property returns TRue if the method1 delegate has completed its operation or false if it has not. This property can be called continuously within a loop to check whether the delegate has finished.

Once the method1 delegate has finished its asynchronous processing, the results of the operation can be retrieved through a call to the EndInvoke method. The compiler also creates this method dynamically, so that the return value of the delegate can be accessed through the EndInvoke methodas well as any out or ref parameters that the delegate accepts as parameters.

The way that EndInvoke works in general is that it returns an object of the same type as the return value of the delegate and has the same out and ref parameters as the initial delegate. An EndInvoke method called on a delegate of the following signature:

 public delegate long Foo(ref int i, out string s, bool b); 

will be defined as follows:

 public long EndInvoke(ref int i, out string s, IAsyncResult result) 

Notice that the return type is a long and only the ref and out parameters of the original delegate are in the signature for this method. The EndInvoke method parameters contain only those original method parameters marked as ref or out. The IAsyncResult (result) is the context handed back from the initial call to BeginInvoke.

If the asynchronous delegate throws an exception, the only way to obtain that exception object is through the EndInvoke method. The EndInvoke method should be wrapped in an exception handler.


Once the while loop of the PollAsyncDelegate method in this recipe is exitedmeaning that the asynchronous delegate has completedthe EndInvoke method can be safely called to retrieve the return value of the delegate as well as any ref or out parameter values. If you want to obtain these values, you must call the EndInvoke method; however, if you do not need any of these values, you may leave out the call to the EndInvoke method.

See Also

See the "IAsyncResult Interface," "AsyncResult Class," "BeginInvoke Method," and "EndInvoke Method" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net