我的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(Debug> Run),它会跳过我的catch块并显示“Later,alligator”消息。
实际上粘贴“void CodeThatThrowsMyOwnException(){将新的MyOwnException(”Shallow“);}”代码放入我的代码中(而不是调用我的真实代码)并逐字地调用“CodeThatThrowsMyOwnException();”然而,在try块中确实会在catch块中显示消息。
据我所知,我没有创建任何线程,我已经找到了try {} catch {}块,它们可以捕获所有异常但在相关项目中找不到任何内容(如果它们在那里,为什么会这个catch块还能在我同事的机器上运行吗?)
通过双击可执行文件来运行我的代码奇怪地在我的机器上给出了一个未处理的异常,在同事的机器上也是如此。这是一条线索,让我尝试以下方法:
当我在我的代码内部的抛出MyOwnException(“Deep Inside”)行放置一个断点时,调用堆栈在我的异常处理程序和我调用'throw MyOwnException的地方之间包含一行“[External Code]” “在深处”)'。如果我将try / catch MyOwnException块放在远离throw的位置(但是在[External Code]的这一侧,我仍然可以捕获异常,在我放置try catch块的任何地方(在函数链的相关部分周围): / p>
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)。)
答案 0 :(得分:1)
treeview_AfterSelect将被称为[外部代码],被称为大多数。这些将是用户选择节点的结果,或者甚至是表单正在加载并且您正在添加节点(我怀疑可能在未处理的异常上发生)。
如果AfterSelect处理程序由于某种原因要抛出异常,则不能依赖调用代码来处理这些异常。否则,调用AfterSelect的任何其他方式都可能导致未处理的异常。