窗体应用程序中的“未处理异常”触发时,消息框不显示

3

我想要为我的应用程序添加 "AppDomain.CurrentDomain.UnhandledException" 处理程序。如果我将错误记录到文本文件中,则可以正常工作。但是,当我尝试使用 MessageBox 时,它从未弹出。这是 .Net 的另一个 bug 吗?有什么想法吗?

这是我的代码示例:

   AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);
   Application.Run(new Form1());

这是我的处理程序方法:

static void CurrentDomain_UnhandledException (object sender, UnhandledExceptionEventArgs e)
{
    try
    {
       Exception ex = (Exception)e.ExceptionObject;

       MessageBox.Show("Whoops! Please contact the developers with "
                   + "the following information:\r\n\r\n" + ex.Message + ex.StackTrace,
                   "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);

    }
    finally
    {
       Application.Exit();
    }
}
编辑: 我尝试了所有可能的选项,但仍然无法看到MessageBox。现在的问题是当我从Visual C#运行它(调试模式)时,它可以完美地显示弹出框。但当我直接从debug/release文件夹运行应用程序时,它不会显示MessageBox,并且应用程序会一直运行,就好像没有发生错误一样...

我对你的代码没有任何问题,一切都很好...(我已经尝试使用 .net 2.0 和 4.0 进行编译,两者都可以工作) - punker76
@punker76 - 嗯,这很奇怪。你使用的是64位机器吗? - Desolator
我在64位机器Win7和VS2010上编译为Debug/Release x86。 - punker76
@punker76 - 我已经更新了问题并提供了更多信息... 当我在VC#调试模式下运行它时,消息框显示为“ok”。但是当我直接从调试文件夹中运行它(双击exe),消息框永远不会弹出。 - Desolator
该函数实际上是从一个新线程中执行的。这是个问题。MessageBox 是一个对话框,就像任何对话框一样,它需要一个所有者窗口才能置于顶层。Winforms 无法为在工作线程上运行的代码找到这样的所有者。消息框仍然显示,但很可能出现在主窗口下面。 - Hans Passant
该功能实际上是从一个新的线程中执行的。这是一个问题。MessageBox是一个对话框,就像任何对话框一样,它需要一个拥有者窗口来置顶显示。Winforms无法为在工作线程上运行的代码找到这样的拥有者。消息框仍然会显示,但很有可能出现在主窗口下方。 - Hans Passant
3个回答

1

可能的情况是因为 Unhandled Exceptions 会导致应用程序静默终止,而 UnhandledExceptionEventHandler 处理非 UI 线程异常。

请查看 Application.SetUnhandledExceptionMode 方法,AppDomain.UnhandledException 事件和 Application.ThreadException 事件

编辑: 根据第一个链接尝试设置 Application.SetUnhandledExceptionMode

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); //add this line

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);    
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());

不,情况并非如此。我已尝试了所有可能的选项,但仍然无法看到MessageBox。现在的问题是,当我从Visual C#(调试模式)运行它时,它完美地显示了该框。但是,当我直接从debug/release文件夹运行应用程序时,它从未显示MessageBox... - Desolator
@RobinVanPersi 在订阅事件之前尝试使用 Application.SetUnhandledExceptionMode 方法。请参见编辑部分。 - S2S2
同样的事情...没有改变..请尝试直接从调试文件夹运行生成的应用程序。 - Desolator

1

这个例子在我的VS2010的调试模式和发布模式下都可以工作:

using System;
using System.Windows.Forms;

namespace WinFormsStackOverflowSpielWiese
{
  internal static class Program
  {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    private static void Main() {
      System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
      System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
      AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }

    private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) {
      try {
        var exception = e.Exception != null ? e.Exception.Message + e.Exception.StackTrace : string.Empty;
        MessageBox.Show("Whoops! Please contact the developers with the following information:\r\n\r\n" + exception,
                        "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
      }
      finally {
        Application.Exit();
      }
    }

    private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
      try {
        var exception = e.ExceptionObject is Exception ? ((Exception)e.ExceptionObject).Message + ((Exception)e.ExceptionObject).StackTrace : string.Empty;
        MessageBox.Show("Whoops! Please contact the developers with the following information:\r\n\r\n" + exception,
                        "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
      }
      finally {
        Application.Exit();
      }
    }
  }
}
表单的代码

编辑现在加入了一个计时器,结果相同...

using System.Windows.Forms;

namespace WinFormsStackOverflowSpielWiese
{
  public partial class Form1 : Form
  {
    private System.Threading.Timer myTimer;

    public Form1() {
      this.InitializeComponent();

      this.myTimer = new System.Threading.Timer(state =>
                                                  {
                                                    var i = 0;
                                                    var s = 100 / i;
                                                  }
                                                , null, 5000, 5000);
    }
  }
}

这部分代码已经有所进展。但是当异常发生在不同的位置时,它就永远不会弹出...我正在使用一个计时器,并且有一个函数每3秒钟从该计时器运行。实际上,该函数是从新线程执行的。现在我真的不知道是什么原因导致了这种情况,为什么会发生。但我猜这可能比看起来的问题更大...无论如何,谢谢。 - Desolator

0
有点晚了,但这里没有展示可行的解决方案。我添加了

Application.DoEvents();

就在消息框之前,现在显示了MessageBox。

希望这能帮助到某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接