IDisposable.Dispose永远不会在使用块后发生异常之后调用

问题描述 投票:2回答:3

[我从thisthis等许多来源了解,如果Dispose块中引发异常,则将始终调用IDisposableUsing方法。因此,我有了这段代码:

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方法。为什么?

c# .net exception idisposable using-statement
3个回答
11
投票

[Environment.Exit将终止程序

如果从try或catch块调用Exit,则任何块不执行。如果使用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();
}

2
投票

请注意,如果您已向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)。请注意,即使在这里,终结器也有可能无法运行,因为它们有运行时间的限制see


0
投票

是!因为在事件处理程序中已调用Environment.Exit(0),所以将无法调用Dispose方法中的代码。

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

© www.soinside.com 2019 - 2024. All rights reserved.