【问题标题】:C# Exceptions only caught when debugging? [duplicate]C# 异常仅在调试时捕获? [复制]
【发布时间】:2011-02-25 04:52:10
【问题描述】:

可能重复:
Exception handling problem in release mode

我怀疑对此有一个非常简单的解释,但我似乎找不到。

当我的 WinForms C# 4.0 应用程序将自身加载到 Program.cs 文件中时,整个 Main() 函数内部都有一条 try/catch 语句。

我写了一个小异常包装器,它的行为与 vanilla .net “未捕获异常”框非常相似,除了它提供了更多信息,允许保存(序列化)异常树,它允许用户直接将错误报告提交给我。

现在,它在调试 (F5) 时工作​​正常。如果我在主线程中的程序中触发异常 anywhere,如果没有 try/catch,则异常会一直触发到 Main() 并显示自定义窗口。

(所有其他我已考虑并得到适当处理的例外情况)。

当我简单地通过运行 .exe 文件来运行程序时,会出现 vanilla .net 异常框,而不是我编写的那个。

您有什么理由可以想到为什么会发生这种情况? 最奇怪的是,它在调试模式下运行与单独运行时的行为完全不同。 我正在构建调试 - 不是发布。

编辑(2011 年 3 月 22 日):

我只是在这里添加一个小附录,以防你们中的一些人在下面接受的答案中找不到隐藏在 cmets 中的答案: 忘记我说我是作为调试而不是发布来构建的。这无关紧要 - 我只是添加它以获得更多信息。重要的是,当我在 VS 中调试ging 时,异常会按预期捕获,但在 VS 之外执行我的 EXE 时却不会。

正如 Cody 所说,Application.Run() 有自己的异常处理程序,这就是为什么它们永远不会到达我的主要catch,但是我提到我什至没有在我的代码中的任何地方使用Application.Run()...而是我的GUI 首次使用Form.ShowDialog() 启动。

我做了一些实验,可以确认Form.ShowDialog() 的行为与Application.Run() 相同,因为异常是在方法本身内处理的。

【问题讨论】:

  • 你确定它的处理程序代码不会生成“不漂亮”的异常框吗?
  • @Cody Gray,我能否与您确认一下:我的代码中的任何地方都没有调用 Application.Run。您将我标记为重复的线程以及您在此处对我的问题的回答都表示通用 .Net 错误框是由Application.Run 的内部事件处理程序生成的。这似乎与我的源代码冲突。 (?)
  • 查看我对您对我的回答的评论的回答(哇,这有意义吗?)。如果是这种情况,这似乎不是“完全重复”,但我们无法知道这一点,因为您没有发布您的源代码。始终将代码的适用部分包含在问题中是一个好主意的原因。由于我们经常被要求进行心理调试,因此我们有时会比有时更相信自己的直觉。

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


【解决方案1】:

这是预期的行为。

您看到的差异是应用程序在附加调试器的情况下运行的结果。当您从 Visual Studio 中启动它时,会自动附加调试器(当然,除非您选择“不调试就启动”)。这会禁用内置的异常处理程序,该处理程序负责向您显示“vanilla”.NET 异常对话框。从 VS 外部启动它不会附加调试器,而是启用内置的异常处理。 (请注意,这与在“调试”模式和“发布”模式下编译程序无关。)

有关详细信息,请参阅 the accepted answerthis related question。我不相信 VB.NET 和 C# 之间的区别在这种情况下是相关的。

正如该答案所述,一种禁用内置异常处理程序的方法。但在选择这样做之前,我建议重新考虑您的方法。您可以考虑处理内置的AppDomain.UnhandledException event,而不是将整个Main 方法包装在一个try-catch 块中,即sounds like a bit of a code smell to me。 Jeff Atwood 发表了一篇很棒的文章 here on Code Project,关于如何用您自己的更用户友好的方法替换标准的 .NET 异常处理。随着 .NET FW 的更高版本改进了 AppDomain.UnhandledException 事件的处理方式,他提出的解决方案变得更加优雅。

【讨论】:

  • 我认为您错过了这个问题。
  • @Kragen:为什么会这样?可能是这样;你能澄清一下我读错了什么吗?我很乐意相应地修改/删除我的答案。
  • @Cody 在调试器中运行时,应用程序会显示一个自定义异常对话框,这表明没有完全未处理的异常,因此不应出现默认异常处理程序。
  • @Kragen:这也是我阅读问题的方式。区别在于 Application.Run 方法中内置的异常处理程序是否启用。当您在调试器下运行时,它被禁用,因此 Main 方法周围的 try-catch 块正在处理异常。当您没有在调试器下运行时,内置的异常处理会接管并在异常向上传递到您的 Main 方法的 try-catch 块之前显示对话框。
  • @Cody Ah - 我没有意识到未处理的异常是在Application.Run内部 处理的,或者如果附加了调试器,则此行为被完全禁用。出于某种原因,我总是认为Application.Run 抛出了未处理的异常,尽管考虑到它,我意识到这将是多么荒谬!
猜你喜欢
  • 2011-09-02
  • 1970-01-01
  • 2014-06-03
  • 1970-01-01
  • 2013-12-01
  • 2019-03-28
  • 2017-11-18
  • 2021-02-09
  • 2013-10-29
相关资源
最近更新 更多