【问题标题】:Catching an Exception across treeview.Nodes.Add / treeview_AfterSelect event boundary跨 treeview.Nodes.Add / treeview_AfterSelect 事件边界捕获异常
【发布时间】:2010-07-21 23:57:29
【问题描述】:

在我的 WinForms 程序中有一个地方抛出了 MyOwnException。

void CodeThatThrowsMyOwnException()
{
    ...
    throw new MyOwnException("Deep Inside");
    ...
}

在堆栈的更上方,有一个简单的 try/catch 块

try
{
    CodeThatThrowsMyOwnException();
}
catch (MyOwnException moe)
{
    MessageBox.Show("Hit this point in the code! Hurray!");
}
MessageBox.Show("Later, alligator.");

在同事的计算机(像我一样运行 VS 2008 SP1)上显示对话框。在我的电脑上,它永远不会捕获异常,也不会显示对话框。当我在引发异常的行上的代码 (CodeThatThrowsMyOwnException) 深处放置一个断点时,它会命中该行上的断点。如果我按 F5(调试 > 运行),它会跳过我的 catch 块并显示“稍后,鳄鱼”消息。

实际上将“void CodeThatThrowsMyOwnException() { throw new MyOwnException("Shallow"); }”代码粘贴到我的代码中(而不是调用我的真实代码)并直接调用“CodeThatThrowsMyOwnException();”但是在 try 块中确实会在 catch 块中显示消息。

据我所知,我没有创建任何线程,我一直在寻找 try {} catch {} 块来捕获所有异常,但在所涉及的项目中找不到任何异常(如果它们在那里,为什么会这个 catch 块在我同事的机器上还能用吗?)

奇怪的是,双击可执行文件运行我的代码会在我的机器上给我一个未处理的异常,而在我同事的机器上也是如此。这是导致我尝试以下方法的线索:

当我在代码深处的 throw MyOwnException("Deep Inside") 行放置断点时,调用堆栈在我的异常处理程序和我调用 'throw MyOwnException( “在深处”)'。如果我将 try/catch MyOwnException 块放在离 throw 更远的地方(但在 [外部代码] 的这一侧,我仍然可以捕获异常,无论我放置 try catch 块的任何位置(围绕函数链的相关部分):

try
{
    CodeChain(...);
}
catch (DrawException de)
{
    MessageBox.Show("Hurray!"); // being executed, but only on the 'throw' side of the [External Code] part of the call stack
}

但是,当我走出(在堆栈下方)[外部代码]时,异常不会触发。这是出乎意料的:

try
{
    treeview.Nodes.Add(treeNode); // triggers the aforementioned chain of code with MyOwnException thrown
}
catch (DrawException de) // no matter what I do, this will not handle my cursed MyOwnException
{
    MessageBox.Show("Hurray!"); // not being executed
}

这是我的问题的核心:我无法赶上调用堆栈,因为我需要运行大量测试(见下文)。

我有一种假设,即他的调试器在他的调试器中神奇地跨线程边界(或跨外部代码,即 Windows GUI 事件)解除异常,而在其他三种情况下(我的调试器(没有64 位扩展),并且当任何一台机器从 Windows 资源管理器运行 EXE 时,异常)在该线程上真正未处理。

那么我该如何捕捉这个异常呢?重新设计我的整个系统以避免使用 treeview.AfterSelect?显然我不明白例外的限制。

潜在问题?

  • 我有一个代表在那里保持我的系统模块化和可重复使用。可以跨模块边界“通过”委托抛出异常吗?

我要完成什么(测试工具)以及为什么我需要例外

我在自动化测试工具中使用它。我需要通过重放发现这些异常情况并缩小问题范围的动作脚本(文本文件)来修复复杂 GUI 系统中的一些非常棘手的逻辑/算法错误。 (在我的程序中可能没有很好的解决方法,在重写或重构设计方面:我需要在这个 QA 阶段捕获这些异常,在我发布之前修复错误(艰难的算法特殊情况)所以我不让我的用户使用这种有缺陷的软件。这不像我为了好玩而使用异国控制流的异常(参见 Int32.Parse)。)

【问题讨论】:

  • 对于您的奇怪行为,是否有可能在您同事的计算机上 Nodes.Add 调用导致选择更改,但在您的计算机上却没有?
  • @msergeant:这可能正在发生,或者至少是类似的事情。或者,也许他的开发机器或框架上的某些设置允许异常冒泡而不触及外部代码,甚至冒泡外部代码。无论哪种方式,感谢您帮助我摆脱困境。

标签: c# winforms exception-handling treeview


【解决方案1】:

treeview_AfterSelect 将被称为大多数您所说的[外部代码]。这些将是用户选择一个节点的结果,甚至是当表单正在加载并且您正在添加节点时(我怀疑这可能发生在您未处理的异常中)。

如果您的 AfterSelect 处理程序由于某种原因将引发异常,您不能依赖调用代码来处理这些异常。否则,调用 AfterSelect 的任何其他方式都可能导致未处理的异常。

【讨论】:

  • 你的意思是说如果我的 AfterSelect 处理程序抛出 MyOwnExcepion 会导致系统崩溃,因为它已经导致出现未处理的异常框(没有附加调试器)基本上我别无选择,只能抓住它在它转义该处理程序(并进入外部代码,即未处理)之前,然后设计某种方式将数据“手动”传递给调用者(将节点添加到树视图的代码)。我想我必须这样做。有点道理,但很奇怪它在另一台机器上的工作方式。奇怪。
猜你喜欢
  • 2012-03-04
  • 2011-07-03
  • 2012-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
相关资源
最近更新 更多