0

我正在使用后台工作程序,发现 RunWorkerCompleted 事件处理程序中引发的新异常在 Application.ThreadException 处理程序中不可见。例如:Program.cs 中的某处:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += delegate(object o, ThreadExceptionEventArgs args)
        {
            if (args.Exception != null)
                Console.WriteLine("thread error {0}", args.Exception.Message);
        };

        Application.Run(new Form1());
    }

然后在按钮中单击(仅用于测试目的)

        var bw = new BackgroundWorker();
        bw.DoWork += delegate(object o, DoWorkEventArgs args) { /* some calculations here */ };
        bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
        { 
            try
            {
                //in run worker completed exception occurs
                throw new ApplicationException("test exception 1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("throwing new exception");
                throw new ApplicationException(string.Format("catched '{0}'", ex.Message), ex);
            }
        };

        bw.RunWorkerAsync();

程序输出如下:

测试异常1

抛出新异常

线程错误测试异常1

我相信在 Application.ThreadException 处理程序异常中应该出现文本线程错误捕获“测试异常 1”,而不是原始异常。

你能帮我吗 - 为什么会发生以及如何解决?这只是示例代码。实际代码中的 RunWorkerCompleted 处理程序中有几个嵌套方法。其中一些方法捕获异常,并在内部异常中抛出带有附加信息和原始异常的新异常。因此,在 Application.ThreadException 处理程序中,我不仅想获得抛出的原始异常,还想获得整个链。

谢谢


我发现 GetBaseException 不会因按钮单击引起的未处理异常而被调用(例如)

让我们假设 Program.Main 方法中有 TreadException 事件处理程序,如下所示:

        Application.ThreadException += (o, args) =>
        {
            Console.WriteLine("BEGIN ThreadException handler");
            ShowException(args.Exception);
            Console.WriteLine("END ThreadException handler\r\n");
        };

和 Program.ShowException 方法是这样的:

    static void ShowException(Exception ex)
    {
        var tab = "";
        while (ex != null)
        {
            Console.WriteLine("{1}error '{0}'", ex.Message, tab);
            tab += '\t';
            ex = ex.InnerException;
        }
    }

当代码

        try
        {
            throw new ApplicationException("button click 1");
        }
        catch (Exception ex)
        {
            throw new ApplicationException(string.Format("BC caught '{0}'", ex.Message), ex);
        }

在单击按钮时执行,它会产生以下输出:

BEGIN ThreadException 处理程序

错误'BC 捕获'按钮单击 1''

  • 错误'按钮单击 1'*

END ThreadException 处理程序

如您所见 - 整个异常链都可用。

但是 ThreadException 处理程序仅显示 RunWorkerCompleted 事件处理程序中非常相似的代码的原始异常(下面的代码在按钮单击事件中执行):

        var bw = new BackgroundWorker();
        bw.DoWork += delegate(object o, DoWorkEventArgs args) 
        { 
            /* some calculations here */
        };
        bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
        { 
            try
            {
                //in run worker completed exception occurs
                Console.WriteLine("RWC exception test, throwing");
                throw new ApplicationException("test exception 1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("RWC got exception, throwing new");
                throw new ApplicationException(string.Format("RWC caught '{0}'", ex.Message), ex);
            }
        };

        bw.RunWorkerAsync();

输出如下:

RWC 异常测试,抛出

测试异常1

RWC 有异常,抛出新的

BEGIN ThreadException 处理程序

错误“测试异常 1” ——这里只有原始异常

END ThreadException 处理程序

似乎 GetBaseException 仅针对 RunWorkerCompleted 事件执行。

4

1 回答 1

1

无论出于何种原因,框架都会调用Exception.GetBaseException您抛出的异常并使用异常传递给ThreadException事件。如果您不希望这样,请不要传入基本/内部异常。

于 2012-09-18T16:40:03.727 回答