.NET Core:Linux上未处理的异常未调用finally块 [英] .NET Core: Finally block not called on unhandled exception on Linux

查看:60
本文介绍了.NET Core:Linux上未处理的异常未调用finally块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了以下C#程序:

I have created the following C# program:

namespace dispose_test
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var disp = new MyDisposable())
            {
                throw new Exception("Boom");
            }
        }
    }

    public class MyDisposable : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("Disposed");
        }
    }
}

当我使用 dotnet run 运行此代码时,我看到以下行为:

When I run this using dotnet run, I see the following behavior:

  • Windows:写入控制台的异常文本,大约20秒后显示"Disposed",程序退出.
  • Linux:写入控制台的异常文本,程序立即退出.从未写过处置".

Windows上的延迟很烦人,但是Linux上根本没有调用Dispose()的事实令人困扰.这是预期的行为吗?

编辑以下对话中的澄清/补充:

EDITS Clarifications/additions from the conversation below:

  • 这并不特定于 using/Dispose(),这只是 try/finally 的特例.通常在 try/finally 中也会发生该行为- finally 块不会运行.我已经更新了标题以反映这一点.
  • 我还通过将文件写入文件系统检查了 Dispose()的执行,只是为了确保问题与在 Dispose之前将stdout与控制台断开连接无关()在未处理的异常的情况下运行.行为是一样的.
  • 如果在应用程序内的任何地方捕获到异常,都会调用
  • Dispose().在这种情况下,应用程序完全无法处理此行为.
  • 在Windows上,较长的间隔不是由于编译延迟引起的.我开始计时何时将异常文本写入控制台.
  • 我最初的实验是在两个平台上都进行 dotnet run ,这意味着要进行单独的编译,但是我也尝试过在Windows上进行 dotnet publish 并直接在该平台上运行输出两个平台,结果相同.唯一的区别是,当直接在Linux上运行时,在异常文本之后写上"Aborted(core dumped)"文本.
  • This is not specific to using/Dispose(), which is just a special case of try/finally. The behavior also occurs generally with try/finally - the finally block is not run. I have updated the title to reflect this.
  • I have also checked for the execution of Dispose() by writing a file to the filesystem, just to ensure that problem wasn't related to stdout being disconnected from the console before Dispose() is run in the case of an unhandled exception. Behavior was the same.
  • Dispose() does get called if the exception is caught anywhere within the application. It's when it goes completely unhandled by the application that this behavior occurs.
  • On Windows, the long gap is not due to compilation delay. I started timing when the exception text was written to the console.
  • My original experiment was doing dotnet run on both platforms, which means separate compilations, but I have also tried by doing dotnet publish on Windows and directly running the output on both platforms, with the same result. The only difference is that, when run directly on Linux, the text "Aborted (core dumped)" is written after the exception text.

版本详细信息:

  • dotnet --version -> 1.0.4.
  • 编译为在.NET Core 1.1上运行的netcoreapp1.1.
  • lsb-release -d -> Ubuntu 16.04.1 LTS
  • dotnet --version -> 1.0.4.
  • Compiling to netcoreapp1.1, running on .NET Core 1.1.
  • lsb-release -d -> Ubuntu 16.04.1 LTS

推荐答案

官方回复是这是预期的行为.

足够有趣的是, C#文档最终尝试页面上的明确地在顶部(强调我的名字)

Interestingly enough, the C# doc page on try-finally explicitly calls this out right at the top (emphasis mine)

在已处理的异常中,可以保证关联的finally块可以运行.但是,如果未处理异常,则finally块的执行取决于异常展开操作的触发方式.而这又取决于计算机的设置方式.有关更多信息,请参见CLR中的未处理异常处理.

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up. For more information, see Unhandled Exception Processing in the CLR.

通常,当未处理的异常结束应用程序时,是否运行finally块并不重要.但是,如果在即使在那种情况下都必须运行的finally块中有语句,则一种解决方案是在try-finally语句中添加catch块.或者,您可以捕获可能在调用堆栈上方的try-finally语句的try块中引发的异常.也就是说,您可以在调用包含try-finally语句的方法的方法中,在调用该方法的方法中或在调用堆栈中的任何方法中捕获异常.如果未捕获到异常,则finally块的执行取决于操作系统是否选择触发异常展开操作.

Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.

我在实验中发现的一件事是,它似乎不足以捕获,您也必须处理.如果执行通过 throw 离开 catch 块,则最终将不会运行.

One thing I found in my experimentation is that it doesn't appear to be enough to catch the exception, you have to handle it as well. If execution leaves the catch block via a throw, the finally will not run.

这篇关于.NET Core:Linux上未处理的异常未调用finally块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆