C# 为什么内部异常到达ThreadException处理程序而不是实际抛出的异常?

C# 为什么内部异常到达ThreadException处理程序而不是实际抛出的异常?,c#,winforms,multithreading,exception-handling,C#,Winforms,Multithreading,Exception Handling,当抛出异常并在应用程序.ThreadException事件处理程序中捕获它们时,我看到了一些wierd行为 基本上,在下面的示例中发生的是在BackgroundWorker的DoWork事件处理程序中抛出异常。RunWorkerCompleted事件处理程序重新调用一个新异常,原始异常作为内部异常 为什么内部异常显示在ThreadException事件处理程序中,而不是抛出的acutal异常?如果我没有在RunWorkerCompleted事件处理程序中提供内部异常,则会显示正确的异常 usin

当抛出异常并在
应用程序.ThreadException
事件处理程序中捕获它们时,我看到了一些wierd行为

基本上,在下面的示例中发生的是在
BackgroundWorker
DoWork
事件处理程序中抛出异常。
RunWorkerCompleted
事件处理程序重新调用一个新异常,原始异常作为内部异常

为什么内部异常显示在
ThreadException
事件处理程序中,而不是抛出的acutal异常?如果我没有在
RunWorkerCompleted
事件处理程序中提供内部异常,则会显示正确的异常

using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace WierdExceptionApp
{
    class WierdExceptionForm : Form
    {
        BackgroundWorker worker = new BackgroundWorker();

        public WierdExceptionForm()
        {
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            worker.RunWorkerAsync();
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                throw new Exception("worker_RunWorkerCompleted", e.Error);
            }
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            throw new Exception("worker_DoWork");
        }

        [STAThread]
        static void Main()
        {
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
            Application.Run(new WierdExceptionForm());
        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message);
        }
   }
}

最后你会得到“内在的”。这似乎是应用程序\u ThreadException方法查看最内部异常的行为。

RunWorkerCompleted事件由使Control.Invoke()工作的WF管道从BGW线程封送到UI线程。本质上,存在一个包含委托的队列,该队列被消息循环清空。执行此操作的代码Control.InvokeMarshaledCallbacks()将在调用堆栈上看到,它有一个catch(Exception)子句来捕获未处理的异常。该子句调用Application.OnThreadException,传递Exception.GetBaseException()的值


这就解释了为什么你只看到内部异常。为什么这样做有点不清楚。可能是要切掉UI线程中的代码堆栈帧,否则会非常混乱,因为真正的异常来自后台线程。

WinForms中的另一个错误,Microsoft肯定永远不会修复!这是多么愚蠢啊!微软肯定永远不会解决这个问题,因为这将是他们眼中的“突破性变化”。不管怎样,还是让我们一起去登记这个问题吧;多年来,这一直在困扰着我,而我却没有意识到。我会看到这些偶尔的错误报告,我发誓我已经处理过了。它们非常罕见,以至于没有花很多时间去研究它们,但最终它开始发生在一些重要的事情上,我意识到例外情况正在发生变化。世界跆拳道联盟??
        if (e.Error != null)
        {
            throw new Exception("worker_RunWorkerCompleted", new Exception("Inner", new Exception("Inner inner")));
        }