异步委托调用中的未处理异常

时间:2011-07-13 13:33:30

标签: .net exception-handling asynchronous delegates

我正在尝试从异步委托调用中捕获未处理的异常。以下程序说明了该问题。我得到以下输出:

Delegate called.
Unhandled exception: an exception.

Delegate called.
EndInvoke() threw an exception: an exception.
Program ended.

Delegate called.
EndInvoke() threw an exception: an exception.
Program ended.
Unhandled exception: an exception.

不同的结果是由于同步问题。如何修复通话?

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");
        }
    }
}

1 个答案:

答案 0 :(得分:2)

异步调用委托时,您有两种选择。

选项1:无回调。我怀疑这就是你要做的事情。

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)
{
    //
}

选项2:回调。

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.

两种形式都是正确的 - 无论你使用哪种形式取决于你正在做什么。正如你所做的那样,它们通常不会合并。