Table of Contents Previous Section Next Section

Recipe 5.17 Handling Exceptions Thrown from an Asynchronous Delegate

Problem

When using a delegate asynchronously, you want to be notified in the calling thread if the delegate has thrown any exceptions.

Solution

Wrap the EndInvoke method of the delegate in a try/catch block:

using System;
using System.Threading;

public class AsyncAction
{
    public void PollAsyncDelegate( )
    {
        // Create the async delegate to call Method1 and call its BeginInvoke method
        AsyncInvoke MI = new AsyncInvoke(TestAsyncInvoke.Method1);
        IAsyncResult AR = MI.BeginInvoke(null, null);

        // Poll until the async delegate is finished
        while (!AR.IsCompleted)
        {
            System.Threading.Thread.Sleep(100);
            Console.Write('.');
        }
        Console.WriteLine("Finished Polling");

        // Call the EndInvoke method of the async delegate
        try
        {
            int RetVal = MI.EndInvoke(AR);
            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( )
    {
        throw (new Exception("Method1"));    // Simulate an exception being thrown
    }
}

Discussion

If the code in the PollAsyncDelegate method did not contain a call to the delegate's EndInvoke method, the exception thrown in Method1 would simply be discarded and never caught. This behavior is by design; for all unhandled exceptions that occur within the thread, the thread immediately returns to the thread pool and the exception is lost.

If a method that was called asynchronously through a delegate throws an exception, the only way to trap that exception object is to include a call to the delegate's EndInvoke method and wrap this call in an exception handler. The EndInvoke method must be called to retrieve the results of the asynchronous delegate; in fact, the EndInvoke method must be called even if there are no results. These results can be obtained through a return value or any ref or out parameters of the delegate.

See Also

For more on calling delegates asynchronously, see Recipe 7.4.


    Table of Contents Previous Section Next Section