开发者

Unhandled exception in asynchronous delegate call

I'm trying to catch unhandled exceptions from an asyn开发者_运维技巧chronous 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");
        }
    }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜