Recipe18.5.Timing out an Asynchronous Delegate


Recipe 18.5. Timing out an Asynchronous Delegate

Problem

You want an asynchronous delegate to operate only within an allowed time span. If it is not finished processing within this time frame, the operation will time out. If the asynchronous delegate times out, it must perform any cleanup before the thread it is running on is terminated.

Solution

The WaitHandle.WaitOne method can indicate when an asynchronous operation times out. The code on the invoking thread needs to periodically wake up to do some work along with timing out after a specific period of time. Use the approach shown in the following code, which will wake up every 20 milliseconds to do some processing. This method also times out after a specific number of wait/process cycles (note that this code will actually time out after more than 2 seconds of operation since work is being done between the wait cycles):

 public class AsyncAction {     public void TimeOutWakeAsyncDelegate( )     {         // 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);         int counter = 0;         while (counter <= 25 &&             !asyncResult.AsyncWaitHandle.WaitOne(20, true))         {             counter++;             Console.WriteLine("Processing…");         }         if (asyncResult.IsCompleted)         {             int retVal = method1.EndInvoke(asyncResult);             Console.WriteLine("retVal (TimeOut): " + retVal);         }         else         {             Console.WriteLine("TimedOut");         }     } } 

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 TimeOutWakeAsyncDelegate method like so:

 AsyncAction aa1 = new AsyncAction(); aa1.TimeOutWakeAsyncDelegate(); 

The output for this code looks like this:

 Calling BeginInvoke on Thread 9 Invoked Method1 on Thread 10 retVal (TimeOut): 1 

Discussion

The asynchronous delegates in this recipe are created and invoked in the same fashion as the asynchronous delegate in Recipe 18.4. However, instead of using the IsCompleted property to determine whether the asynchronous delegate is finished processing, WaitHandle.WaitOne is used. This method blocks the thread that it is called on either indefinitely or for a specified length of time. This method will stop blocking the thread when it is signaled by the THReadPool that the thread has completed or timed out and returns a true indicating that the asynchronous processing is finished. If the processing is not finished before the allotted time-out value expires, WaitOne returns false. Note that the WaitOne method that accepts no parameters will block the calling thread indefinitely.

It is usually a better idea to include a time-out value when using the WaitOne method, as this will prevent the calling thread from being blocked forever if a deadlock situation occurs (in which case the thread on which the WaitOne method waits is never signaled) or if the thread running the asynchronous delegate never returns, such as when entering into an infinite loop.


The TimeOutWakeAsyncDelegate method in this recipe will periodically wake up (after 20 milliseconds) and perform some task on the calling thread; unlike the TimeOutAsyncDelegate method, which will continue blocking for the allotted time frame and not wake up. After 25 wait cycles, if the asynchronous delegate has not finished processing, the while loop will be exited, essentially timing out the delegate. If the delegate finishes processing before the 25 wait cycles have completed, the while loop is exited.

The IsCompleted property is checked next to determine whether the asynchronous delegate has finished its processing at this time. If it has finished, the EndInvoke method is called using the IAsyncResult from the initial BeginInvoke call to obtain any return value, ref parameter values, or out parameter values. Otherwise, the delegate has not completed within the allotted time span and the application should be informed that this thread has timed out.

See Also

See the "WaitOne Method" and "AsyncResult Class" 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