繁体   English   中英

IDisposable.Dispose 在使用块异常后永远不会被调用

[英]IDisposable.Dispose is never called after exception in using block

我从像这样这样的许多来源了解到,如果在Using块中抛出异常,将始终调用IDisposableDispose方法。 那么我有这个代码:

static class MainEntryPoint
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException;

        using (var x = new Disposable())
        {
            throw new Exception("asdfsdf");
        }
    }

    private static void HandleUnhandledException(Object sender, System.UnhandledExceptionEventArgs e)
    {
        Environment.Exit(0);
    }
}

class Disposable : IDisposable
{
    public void Dispose()
    {
        System.Diagnostics.Debug.Print("I am disposed");
    }
}

当抛出未处理的异常时,它退出应用程序。 从不调用Dispose方法。 为什么?

Environment.Exit将终止程序

如果从 try 或 catch 块调用 Exit,则任何 finally 块中的代码都不会执行。 如果使用 return 语句,则 finally 块中的代码确实会执行。

using (var x = new Disposable())
{
    throw new Exception("asdfsdf");
}

将被转换为

Disposable x = new Disposable();
try
{
    throw new Exception("asdfsdf");
}
finally
{
    if (x != null)
        x.Dispose();
}

请注意,如果您向Disposable添加了终结器,例如:

public class Disposable : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        Console.WriteLine("I am disposed");

        if (disposing)
        {
            GC.SuppressFinalize(this);
        }
    }

    ~Disposable()
    {
        Dispose(false);
    }
}

(因此使用“完整” IDisposable模式),然后“通常”将调用终结器(因为终结器有机会在Environment.Exit上运行),并且该方法将调用Dispose(bool disposing) 请注意,即使在这里也有可能不会运行终结器,因为它们有运行时间限制,请参阅

确切地! 由于 Environment.Exit(0) 已在事件处理程序中调用,因此无法调用 Dispose 方法中的代码。

尝试删除对 Environment.Exit(0) 的调用并查看是否调用了 Debug.Print()。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM