【发布时间】:2017-10-17 09:25:56
【问题描述】:
我创建了以下 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块未运行。我已更新标题以反映这一点。 - 我还通过将文件写入文件系统来检查
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
【问题讨论】:
-
你应该在异常之前写一些东西到控制台,看看这20秒的延迟是不是编译延迟。
-
您确定没有调用
Dispose吗?难道是它被调用但stdout已经分离?您可以尝试将Console.WriteLine更改为File.WriteAllText并查看是否写入了文件。 -
@FedericoDipuma 是的,也试过了,结果相同——文件是在 Windows 上写入的,而不是在 Linux 上。
-
如果你明确写出
using会发生什么,即使用try/finally?如果添加catch以便实际上处理异常会发生什么? -
听起来像是一个应该报告的错误(例如,通过 Connect 或 GitHub 问题)。根据您的描述,即使存在
finally子句,似乎一个未处理的异常也会在不展开堆栈的情况下破坏进程。我认为这实际上与IDisposable的关系不大,而与finally子句的执行不足有关,无论它们可能包含什么。