Recipe 5.17 Handling Exceptions Thrown from an Asynchronous DelegateProblemWhen using a delegate asynchronously, you want to be notified in the calling thread if the delegate has thrown any exceptions. SolutionWrap 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 } } DiscussionIf 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 AlsoFor more on calling delegates asynchronously, see Recipe 7.4. |