【问题标题】:Application.ThreadException is not called未调用 Application.ThreadException
【发布时间】:2013-06-04 07:59:25
【问题描述】:

我的 WinForms 应用安装了 Application.ThreadException 事件处理程序来处理所有未处理的异常(处理程序显示一个对话框:发生错误,单击此处发送错误报告等)。

问题是当应用程序显示模式对话框时,我的事件处理程序没有被调用。当我显示 MessageBox 或我的异常对话框时,所有异常都会被默默地吞下。有没有办法抓住它们?

以下是模拟此行为的示例 WinForms 应用程序。当此应用程序显示 MessageBox 时,所有在后台抛出的异常都将丢失(不调用 ThreadException 处理程序):

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

class Program
{
  static void Main()
  {
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    var form = new MyForm();
    Application.ThreadException += (s, e) =>
    {
        form.AppendText("ThreadException event handler is called.");
        MessageBox.Show("Error: " + e.Exception);
    };

    Application.EnableVisualStyles();
    Application.Run(form);
  }
}

class MyForm : Form
{
  public MyForm()
  {
    Controls.Add(TextBox = new TextBox
    {
      Multiline = true,
      Dock = DockStyle.Fill
    });

    ThrowUnhandledException(1);
    ThrowUnhandledException(2);
    ThrowUnhandledException(3);
  }

  private async void ThrowUnhandledException(int delaySeconds)
  {
    await Task.Delay(TimeSpan.FromSeconds(delaySeconds));
    AppendText("Throwing a NotImplementedException!");
    throw new NotImplementedException();
  }

  private TextBox TextBox { get; set; }

  public void AppendText(string message)
  {
    TextBox.AppendText(message + Environment.NewLine);
  }
}

编辑。我更新了代码以使事情更清晰。

当抛出异常时,MyForm 会写入 TextBox:抛出 NotImplementedException!

当调用 ThreadException 处理程序时,它会写:ThreadException 事件处理程序被调用。 然后它会显示一个消息框。

如果所有异常都被捕获,我的 TextBox 将显示以下内容:

抛出 NotImplementedException!
调用 ThreadException 事件处理程序。
抛出 NotImplementedException!
调用 ThreadException 事件处理程序。
抛出 NotImplementedException!
调用 ThreadException 事件处理程序。

但它显示:

抛出 NotImplementedException!
调用 ThreadException 事件处理程序。
抛出 NotImplementedException!
抛出 NotImplementedException!

【问题讨论】:

    标签: c# .net winforms exception exception-handling


    【解决方案1】:

    你可以试试替换

    Application.ThreadException += (s, e) => MessageBox.Show("Error: " + e.Exception);
    

    与

    Application.ThreadException += (s, e) => Console.WriteLine(e.Exception); 
    

    您会看到事件处理程序每​​次都会被调用。

    【讨论】:

    • 是的,这就是重点。 在显示 MessageBox 时不调用事件处理程序。尝试写入控制台,然后在您的处理程序中显示一个消息框。
    • @yallie 我明白你的意思。尝试使用awaits 序列化异步调用,如await ThrowUnhandledException(
    • 这部分代码只是一个模拟。在我的真实应用程序中,事件异步发生(即异步服务器调用引发异常)。
    • @yallie 我建议解决它。显示一个非模态表单,或者只是记下队列中的每个异常,然后一个一个地处理它们。
    • 感谢您的建议,我已经尝试过了。异常表单不是我的应用程序中唯一的模态表单,我只是不能强制所有表单都是非模态的。而且我无法拦截每个未处理的异常,因为没有调用 ThreadException 处理程序。
    【解决方案2】:

    我尝试了您的程序,但它似乎对我来说很好。 ThrowUnhandledException 被调用了 3 次。所有三个消息都附加到文本框。

    我尝试添加一个 MessageBox:

    ThrowUnhandledException(1);
    ThrowUnhandledException(2);
    ThrowUnhandledException(3);
    
    MessageBox.Show("Hello");
    

    但这也可以按预期工作。我得到消息框,但如果我在异常处理程序上放置一个断点,它会被调用三次。当我关闭消息框时,我可以在 MyForm 窗口中看到所有三个消息。

    【讨论】:

    • 没错,所有三个消息都被附加到文本框。 但这些消息是在引发异常之前附加的。显示了多少个消息框?
    • 请尝试更新的代码示例。希望它能更清楚地显示问题。
    猜你喜欢
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2011-01-02
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多