Reputation: 4206
I'm trying to catch unhandled exceptions from an asynchronous delegate call. The following program illustrates the issue. I get the following output:
Delegate called.
Unhandled exception: an exception.
or
Delegate called.
EndInvoke() threw an exception: an exception.
Program ended.
or
Delegate called.
EndInvoke() threw an exception: an exception.
Program ended.
Unhandled exception: an exception.
The different results are due to the synchronization issues. How to fix the call?
using System;
namespace AsyncCallback
{
public delegate void SampleDelegate();
public class Program
{
private static SampleDelegate sampleDelegate;
public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
sampleDelegate = ThrowException;
var result = sampleDelegate.BeginInvoke(Callback, null);
Console.WriteLine("Delegate called.");
result.AsyncWaitHandle.WaitOne();
Console.WriteLine("Program ended.");
}
private static void Callback(IAsyncResult result)
{
try
{
sampleDelegate.EndInvoke(result);
Console.WriteLine("EndInvoke() completed.");
}
catch (Exception ex)
{
Console.WriteLine("EndInvoke() threw an exception: {0}.", ex.Message);
throw;
}
}
private static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Unhandled exception: {0}.", (e.ExceptionObject as Exception).Message);
}
private static void ThrowException()
{
throw new Exception("an exception");
}
}
}
Upvotes: 2
Views: 2647
Reputation: 30001
When calling a delegate asynchronously, you have two options.
Option 1: no callback. I suspect this is what you're trying to do.
SomeDelegate d;
IAsyncResult res = d.BeginInvoke(null, null);
//..do some other work in the meantime.
try
{
// EndInvoke will wait until execution completes.
// WaitHandle use not needed!
d.EndInvoke(res);
}
catch(Exception ex)
{
//
}
Option 2: callback.
SomeDelegate d;
d.BeginInvoke(res =>
{
// this is called once the delegate completes execution.
try
{
d.EndInvoke(res);
}
catch(Exception ex)
{
//
}
}, null);
//..do some other work in the meantime.
// everything pertaining to the delegate's completion is done in the callback.
// no exception handling should be done here.
Both forms are correct -- whichever one you use depends on what you're doing. They're not normally combined, as you have done.
Upvotes: 2