gpt4 book ai didi

c# - .NET4.5.1的Try-Catch-Finally阻止问题

转载 作者:可可西里 更新时间:2023-11-01 02:59:16 25 4
gpt4 key购买 nike

我有一个简单的try-catch-finally代码块,该块在.NET3.5中可以按预期工作,但是在使用.NET4.5.1创建的项目中,相同的代码的行为完全不同。基本上,在.NET4.5.1中,如果发生异常(这不是我从try-catch-finally块所期望的行为),则“finally”块不会被命中。我尝试了不同的机器,并且我的另外2个同事也尝试了,我们都得到了相同的结果。这是我关心的问题,因为我使用了finally块来关闭DataReader,某些连接以及诸如此类的东西。

如果在没有调试器的情况下在 RELEASE 模式下引发了异常,或者在运行 RELEASE编译的EXE 文件时,.NET4.5.1不会到达“最终”块。在 Debug模式下,两个.NET版本都击中“finally”块。

再次,下面的代码在没有调试器的.NET3.5 RELEASE模式下表现正常,但在.NET4.5.1中却没有变化。我想念什么吗?有人可以帮忙吗?

class Program
{
static void Main(string[] args)
{
try
{
string a = null;
var x = a.Length;
Console.WriteLine(x);
}
catch (Exception ex)
{
throw;
}
finally
{
Console.WriteLine("This is the finally block.");
}
Console.WriteLine("You should not be here if an exception occured!");
}
}

最佳答案

the code below behaves as expected in .NET3.5 RELEASE mode without debugger but not in .NET4.5.1. Am I missing something?



注意:我夸大了这种行为的不确定性;感谢评论员Voo指出这一点。我应该首先回到规范。

是的。 CLI规范要求CLR在发生未处理的异常时结束程序。如果处理了异常,则仅需要运行finally块。该规范对于在存在未处理的异常时是否需要,允许或不允许执行CLR的问题含糊不清;那么,安全的假设是说这是规范未定义的行为,并且取决于特定的实现。

对于未处理的异常,CLR可以选择运行finally块,也可以不运行。许多人认为CLR使用此算法:在异常情况下,走到调用栈,随心所欲地执行finally块,寻找处理程序;如果找不到处理程序,请终止该过程。在未处理异常的程序中,不需要CLR遵守此算法。特别是,允许​​CLR用黑魔法确定没有异常处理程序,并且从不运行任何finally块。我不知道在某些情况下在某些版本的CLR中是否选择这样做。在任何情况下,您都不能依靠该行为来确保程序的正确性,因为具有未处理异常的程序是不正确的。

该规范还指出,CLR可以一时兴起选择提供或不启动调试器。在调试或发行版本中,CLR不需要执行相同的操作,并且版本之间不需要执行相同的操作。

这里的问题是您根据过去的经验形成了期望,但是没有文档说明过去的经验是对 future 进行预测的基础。相反,恰恰相反。如果有喜好,则CLR可以在有未处理异常的程序中根据月相更改其行为。

如果您希望程序表现正常,请不要抛出未处理的异常。

So if I understand you correctly, as long as there is another catch somewhere upstream, the finally block will execute?



不,我没有那么说。让我们分解一下。

如果程序中有未捕获的异常,则程序的行为是实现定义的。无论您得到什么行为,都是您得到的行为,CLR有权产生该行为。这包括运行finally块和不运行finally块。

假设没有未捕获的异常,并且引发了异常,并且在捕获的途中有一个finally块。是否保证finally块将执行? 没有。有很多事情可以阻止finally块在法律程序中执行。例如,沿途的另一个finally块或异常过滤器可能会陷入无限循环或快速失败,这两种情况都会阻止finally块执行。如果绝对肯定要运行一些清除代码,则需要研究约束执行区。 (我不知道它们是如何工作的;我从来不需要学习。我听说它们很棘手。)

可以保证的是,如果控件离开了一个最终保护的块,那么最终代码将运行。在异常过滤器中运行的代码不算作离开该块,并且快速失败不会导致程序控制退出一个块,而是导致程序控制突然结束。显然,无限循环会导致控制永不退出块。

I suppose in the case of a truly unhandled exception, the program should terminate anyways so an orphaned DB connection/transaction shouldn't be an issue?



不管是不是问题,我都不能说。询问数据库的作者。

该程序很有可能会终止,尽管我再次指出CLR不需要具有这种行为。例如,假设CLR试图弄清是否安装了调试器时,有一些线程继续运行。 CLR有权任意花费很长的时间来解决该问题,因此有权保持该线程运行。不管是不是,我都不知道。我所知道的是,我不想依靠任何一种行为。

Also, does using the 'AppDomain.CurrentDomain.UnhandledException event count as 'handling'



没有。如果该事件运行,则存在未处理的异常,并且程序的行为是实现定义的。该事件处理程序仅应用于执行以下操作,例如记录程序存在错误的事实。

关于c# - .NET4.5.1的Try-Catch-Finally阻止问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30879554/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com