问题
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