c# - .NET 核心 : Finally block not called on unhandled exception on Linux

标签 c# linux .net-core

我创建了以下 C# 程序:

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 运行它时,我看到以下行为:

  • Windows:异常文本写入控制台,约 20 秒后打印“Disposed”,程序退出。
  • Linux:异常文本写入控制台,程序立即退出。 “处置”从未写过。

Windows 上的延迟很烦人,但在 Linux 上根本不调用 Dispose() 的事实令人不安。这是预期的行为吗?

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

  • 这不是特定于using/Dispose(),它只是try/finally 的特例。该行为通常也发生在 try/finally 中 - finally block 未运行。我更新了标题以反射(reflect)这一点。
  • 我还通过将文件写入文件系统来检查 Dispose() 的执行情况,只是为了确保问题与在 Dispose 之前从控制台断开连接的标准输出无关() 在未处理的异常情况下运行。行为是一样的。
  • Dispose() 如果异常在应用程序中的任何位置被捕获,则会被调用。当应用程序完全未处理它时,就会发生此行为。
  • 在 Windows 上,长间隔不是由于编译延迟造成的。当异常文本写入控制台时,我开始计时。
  • 我最初的实验是在两个平台上执行 dotnet run,这意味着单独编译,但我也尝试过在 Windows 上执行 dotnet publish 并直接在上运行输出两个平台,结果相同。唯一不同的是,直接在 Linux 上运行时,异常文本后会写上“Aborted (core dumped)”。

版本详情:

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

最佳答案

Official response这是预期的行为。

有趣的是,C# doc page on try-finally在顶部明确调用它(强调我的)

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.

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 block ,finally 将不会运行。

关于c# - .NET 核心 : Finally block not called on unhandled exception on Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44032931/

相关文章:

linux - 保持 IPFS 守护进程存活的最佳方法

asp.net-core - 为什么需要设置 DefaultForbidScheme

c# - 使用 HttpClient 保留转义的 Uri

c# - WPF:从不同的 UserControls 访问 ObservableCollection

linux - 创建与其他文件相关的符号链接(symbolic link)

c# - InnerException 抛出 TypeLoadException TypeLoadException : Could not load type 'System.UriTemplate' from assembly 'System. ServiceModel,

asp.net-core - Blazor 中的@{} @code{} 和 @function{} 有什么区别?

c# - 长时间保持 C# Filestream 打开是否安全?

c# - 使用 Automapper 映射对象列表

Django 无法访问 Azure 安装的存储