IDisposable.Dispose is never called after exception in using block

我的梦境 提交于 2019-12-02 05:52:44

问题


I understand from many sources like this and this that the Dispose method of an IDisposable will always be called if an exception is thrown in a Using block. So then I have this code:

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");
    }
}

It exits the application when an un-handled exception is thrown. The Dispose method is never called. Why?


回答1:


Environment.Exit will terminate the program

If Exit is called from a try or finally block, the code in any catch block does not execute. If the return statement is used, the code in the catch block does execute.

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

will be converted to

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



回答2:


Note that if you had added a finalizer to Disposable, like:

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);
    }
}

(so using the "full" IDisposable pattern), then "normally" the finalizer would be called (because the finalizers have a chance to run on Environment.Exit), and that method would call Dispose(bool disposing). Note that even here there is the possibility that the finalizer wouldn't be run, because there is a time limit for them to run, see.




回答3:


Exactly! there is no way the code in the Dispose method will be called since Environment.Exit(0) has been called in the event handler.

Try to remove the call to Environment.Exit(0) and see if the Debug.Print() is called.



来源:https://stackoverflow.com/questions/31026257/idisposable-dispose-is-never-called-after-exception-in-using-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!