【问题标题】:How to: generate UnhandledException?如何:生成 UnhandledException?
【发布时间】:2011-02-21 03:10:49
【问题描述】:

我使用这段代码来捕获 WinForm 应用程序 UnhandledException。

[STAThread]
static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new
      System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

    // Set the unhandled exception mode to force all Windows Forms errors 
    // to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException += 
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    try
    {
        Application.Run(new MainForm());
    } catch....

我将尝试重新启动应用程序。现在我的问题是模拟这样的异常。我在尝试之前尝试过(主要):throw new NullReferenceException("test"); VS 抓住了它。

在带有按钮的 MainForm 代码中也试过:

    private void button1_Click(object sender, EventArgs ev)
    {         
        ThreadPool.QueueUserWorkItem(new WaitCallback(TestMe), null);
    }

    protected void TestMe(object state)
    {
        string s = state.ToString();
    }

没有帮助,VS 抓住了它,即使在发布模式下也是如此。

  • 最后我应该如何强制应用程序生成UnhandleldException
  • 我能否重新启动CurrentDomain_UnhandledException 中的应用程序?
  • 如何生成ThreadException

PS。

如果我在 VS 之外启动 一个 windows 通用窗口

Application MyApplication”遇到 一个错误,应该是 关闭...blabla...发送报告/不要 发送。

不过我想VS进入这个方法(...Domain_Unhahdled...)

编辑: 重新启动应用程序时,是否可以 禁用 Windows 崩溃消息,如下所示: alt text http://byfiles.storage.msn.com/y1pOhWnAAXfMYtJH2VNa5iL0l1hjAqNHD2VmVnl8nN6L1oQC_xHkyHCJxhMc1ZLxLOH9ZXfZoo5zX8?PARTNER=WRITER ?

代码:

static void CurrentDomain_UnhandledException(object sender, 
    UnhandledExceptionEventArgs e)
{
    // Since we can't prevent the app from terminating
    // log this to the event log.
    Logger.LogMessage(ERROR, errorMsg);
    Application.Restart();

【问题讨论】:

  • 我不确定我是否理解这个问题...您是在问为什么即使您注册了全局处理程序,Visual Studio 也会中断异常?
  • @Aaronaught:我想进入 CurrentDomain_UnhandledException 方法(我将尝试测试重启应用程序代码),最后我的应用程序死掉了。
  • 请澄清您的意思,“VS 抓住了它”
  • @Rising Star: VS 打破它并且不进入 CurrentDomain_UnhandledException。
  • @serhio: 当你恢复执行,或者当你在 VS 调试器之外运行程序时会发生什么?

标签: .net winforms testing exception-handling throw


【解决方案1】:

我仍然不能完全确定我理解了这个问题,但有几点要提一下:

  • Application.ThreadExceptionApplication.SetUnhandledExceptionMode 仅适用于 Windows 窗体线程。任意的ThreadPool 线程实际上并不是 Windows 窗体线程,即使在 Winforms 应用程序中也是如此,因此这两行代码是无效的。

  • 使用AppDomain.CurrentDomain.UnhandledException 注册事件捕获ThreadPool 线程上发生的异常。

  • 然而UnhandledException 事件实际上无法处理异常。到那时,阻止进程终止已经太晚了,如果后台线程上发生异常,这种情况总是会发生(除非您启用了旧的 .NET 1.1 行为,但是......不要。)此事件是真的只适合记录或清理。

我自己使用与您类似的测试代码对此进行了测试,并验证了异常“处理程序”中的代码确实执行了。但是应用还是会崩溃,而且你无法阻止它。

更新:我将再尝试一次,仅此而已。

如果您的目标是让无人值守的应用程序始终运行,您有以下三种选择:

  1. 正确处理您的异常。到目前为止,这是最好的并且可能唯一正确的解决方案。挂钩 AppDomain.UnhandledException处理异常。当控件进入该事件处理程序时,您的应用程序已经崩溃了。你不能再保存它了。

    从后台线程转义的未处理异常是您代码中需要修复的灾难性错误。从后台线程转义的未处理异常是您需要修复的代码中的灾难性错误。从后台线程转义的未处理异常是您的代码中需要修复的灾难性错误。请不要再出现“我不在乎”的效果 - 您需要开始 关心。

  2. 礼貌地要求 Windows 为您重新启动应用程序。 与尝试从崩溃处理程序重新启动不同,这是一个非常糟糕的主意,原因不胜枚举完全枚举(数据损坏、无限重启循环、资源泄漏、操作系统不稳定等),registering for a restart 实际上允许这种情况以半受控方式发生。正如我在 cmets 中提到的,在 .NET 中使用 interop with this API 很简单。您在应用程序启动时立即注册,而不是在应用程序崩溃并且您的应用程序处于不受信任状态时注册。

  3. 创建一个监控您的应用程序的监督服务,并在它崩溃时重新启动它。由于前两点中讨论的许多原因,这仍然很糟糕,但您至少有一定程度的稳定战斗机会。

    您可以通过使用命名互斥体、在主管中等待它并观察WAIT_ABANDONED 状态(.NET 中的AbandonedMutexException)来获得应用程序崩溃的非常可靠的指示。放弃状态仅在拥有互斥锁的进程终止但未释放它时出现 - 即有未处理的异常。通过更多的互操作黑客攻击,您还可以检测并关闭崩溃窗口。

这些是您的选择。我强烈建议您处理后台线程上的异常,因为从后台线程转义的未处理异常是您需要修复的代码中的灾难性错误。如果它来自外部组件并且您可以' 没有抓住它,那么灾难性的错误就在那个组件中,你应该考虑将它报告给作者或使用不同的组件。

如果应用程序不够稳定而无法真正继续运行,那么仅仅要求“此应用程序必须始终运行并且应该完全忽略致命崩溃”并不能实现这种情况。崩溃就是崩溃。如果发动机突然熄火,您不会设计一辆汽车就立即重新启动。您能做的最好的事情就是让受信任的操作员(无论是人工操作员、操作系统还是某些监控软件)代表它重新启动应用程序。

这个问题的变体似乎经常出现 - 基本上,“我的应用程序永远不应该崩溃,或者如果它崩溃了,它应该是不可见的。我想吃掉所有未处理的异常并假装它没有发生。”这不仅是不可能的,而且与几乎所有优秀设计的原则背道而驰(尤其是“快速失败”原则,当然可以重新解释,但绝不能完全忽略)。

我只能这么说。如果您不愿意接受其中任何一个,那么祝您找到可行的替代方案。

【讨论】:

  • Application.ThreadException 几乎与线程无关,但与 Windows 事件(如 Click 等)有关。对于其他事件,我可以同意,但最后,我怎样才能让 VS 进入我的“ handler" 方法,这就是问题所在。
  • @serhio:我知道,这就是我要说的,显示这两个事件的代码没有意义,它们在这里不相关。我所说的是 VS 确实进入了事件处理程序,所以如果它在你的情况下没有这样做,那么你需要发布步骤来重现。
  • 不,绝对不可能阻止 Windows 崩溃对话框出现并自动“重新启动”。正如我所说,一旦您到达AppDomain.UnhandledException 为时已晚,无法防止崩溃。崩溃已已经发生,这只是您进行损坏控制或尝试记录某些内容的一种方式。这开始看起来像另一个“我怎么能忽略所有异常”的问题 - 你不能
  • @Aaronaught,我不想防止崩溃,我不想显示 Windows 消息,因为我重新启动了我的应用程序,但消息仍然存在。 用户无法与屏幕交互。(例如,我的应用程序显示在火车乘客屏幕上)
  • @serhio:如果您不希望出现崩溃对话框,请不要让您的应用程序崩溃。 即使您可以吞下全面崩溃,这将是一个非常糟糕的主意,甚至比在未处理的异常事件中重新启动 Winforms 应用程序更糟糕。如果您绝对需要这种级别的隔离,如果您必须执行一些您知道可能“崩溃”但由于某种原因不能让您的整个应用程序停机的操作,那么在一个单独的进程中执行该操作,一个没有任何用户界面。但老实说,只需修复错误并编写强大的线程代码。
【解决方案2】:

Visual Studio 可能设置为在出现异常时中断,但如果您继续单步执行代码,它仍应遵循您想要的路径。您还应该尝试在 VS 之外运行该应用。

在出现未处理的异常后重新启动应用程序是个坏主意,因为您(根据定义)处于未知状态。如果异常条件从未改变,重新启动,如果可能的话,可能会使您进入一个永无止境的重新启动循环。相反,请考虑尝试将异常信息记录到 Web 服务器,以便调查和修复崩溃。不过,请务必在上传崩溃数据之前获得用户的许可。

【讨论】:

  • 我的应用程序可以重新启动,因为我会定期执行一些操作。即使其中一个失败,也最好是另一个继续。如果我处于异常状态,我将无法继续前进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 2017-02-23
  • 2013-05-19
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
相关资源
最近更新 更多