这是一个非常奇怪的问题。我们有一个包含多个Catch块的Try Catch。第一个Catch块没有代码,只有注释。
Try
'Some Code
Catch ex As ThreadAbortException
'Do Nothing
Catch ex As Exception
HandleException(ex)
End Try
如果抛出ThreadAbortException以外的异常,则会被第二个Catch捕获,如预期的那样。但是,当在VS2010中单步执行代码时,ex对象在这种情况下是Nothing。到目前为止,我们已经找到了两种“修复”此问题的方法。
修复1: 重命名第一个异常变量。
Try
'Some Code
Catch tex As ThreadAbortException
'Do Nothing
Catch ex As Exception
HandleException(ex)
End Try
修复2:将任意代码行添加到第一个Catch块。
Try
'Some Code
Catch ex As ThreadAbortException
Dim i As Integer = 1
Catch ex As Exception
HandleException(ex)
End Try
在上述任何一种情况下,HandleException中的代码在运行时似乎仍能正常运行。这是Visual Studio或调试器中的错误吗?或者我们在这里遗漏了什么,上面第一段代码无效?
这一切都在.NET 4.0中完成。
答案 0 :(得分:15)
Teejay有正确答案。
但是,如果您的Catch
块为空,则完全没有理由处理此异常。你只是想阻止最后一个块捕获它。你可以使用你的方法 - 但是考虑到一个空的Catch
块通常是不可接受的:异常应该被捕获,或者应该被正确处理;静静地吞咽它们必须被视为一种虫子。您的情况是此规则的一个例外,但因此需要在代码中记录,因为否则会使细心的维护者感到困惑。
嗯,对于这种情况,VB有一个特殊的习惯用语:
Try
' …
Catch ex As Exception When Not TypeOf ex Is ThreadAbortException
' Only executed if `ex` isn’t a ThreadAbortException
End Try
此代码根本无法捕获ThreadAbortException
,如果您不想处理它,这是正确的做法:ThreadAbortException
无法被吞下即使你抓住了它,它也会在Catch
块的末尾重新抛出。
请注意,这与使用传统If
语句的SysDragon的答案根本不同,而此处的代码使用Catch
语句中的特殊子句作为过滤器。
答案 1 :(得分:5)
这似乎是VS'调试器错误。
<强> PROOF 强>
如果你写:
Try
Throw New InvalidOperationException("MESSAGE")
Catch ex As ArgumentException
'Do Nothing
Catch ex As Exception
Debug.WriteLine(ex)
End Try
并且您在{em> Quickwatch模式中查看ex
评估为Nothing
的 BUT 强> 的
在控制台中程序正确打印System.InvalidOperationException: MESSAGE
答案 2 :(得分:-2)
好的,让我详细说明......
看来你必须在每个捕获中都有一个“结果”。如果您只是希望特定捕获没有发生任何事情,请不要包含它,或将其移动到代码中的其他位置。
Try
'Some Code
Catch ex As ThreadAbortException
'Do something(ex: HandleExceptionSub())
Catch ex As Exception
HandleException(ex)
End Try
如果你“抓住”一个例外,你必须对它做点什么。
编辑:
我也找到了这些信息,可以帮助您进一步了解try catch的工作方式:
多个捕获块
try块可以抛出多个异常,可以通过使用多个catch块来处理。请记住,更专业的catch块应该在广义块之前出现。否则编译器将显示编译错误。 Multiple Catch Blocks
调试器不是“Bug”。调试器旨在帮助您查找和处理所有异常。
编辑: 似乎可以完全避免我在另一篇文章中读到的这个异常。而且似乎最好避免异常,而不是不处理它。 Handling ThreadAbortException
编辑: 刚刚在try中找到了有关多个catch块的更多信息。这是来自MSDN并声明永远不会到达空白catch块后的catch块... Try Catch Finally Statement 进一步证明这不是一个错误,而是强制处理代码中所有异常的预期功能。
编辑: 为了在评论中直接设置一些人,我创建了一个非常简单的测试程序,看看这确实是一个bug。我的发现是捕获块完美地工作。似乎遵循MSDN记录的创建具有多个Catch块的Try Catch的方式可以像它们所说的那样工作。
private void button1_Click(object sender, EventArgs e)
{
try
{
if (textBox1.Text == "")
{
throw new ArgumentNullException("textBox1", "TextBox can not be empty");
}
else
{
MyString(textBox1.Text);
}
}
catch (ArgumentNullException ex)
{
//nothing
}
catch (Exception ex)
{
MessageBox.Show("Test: " + ex.Message);
}
}
private int MyString(string text)
{
return int.Parse(text);
}
我创建了一个带有按钮和文本框的简单表单。如果文本框为空,则抛出ArgumentNullException,并在“MyString”中将字符串解析为抛出“FormatException”的整数。有一个空白的catch块,这不是处理“捕获”异常的正确方法确实有效。所以据我所知,这不是一个错误。显然我唯一同意Teejay和Konrad的意思是你不能使用try catch方法捕获和处理ThreadAbortException。 Konrad的解决方案是编写try catch代码的最佳方式。