如果程序意外退出(异常退出或进程终止),会发生什么?是否存在这样的情况(或其他情况),程序将终止,但IDisposable
对象不会被正确地处理?
我之所以问这个问题,是因为我正在编写与外围设备通信的代码,并且我希望确保它不会处于糟糕的状态。
发布于 2015-12-25 08:04:06
如果原因是异常,并从using
块或try catch finally
块中抛出,则将按应有的方式处理。如果它没有被using
块捕获,它就不会自动释放(就像应用程序正常关闭时那样)。
样本:
IDisposable d1 = new X();
using (IDisposable d2 = new X())
{
throw new NotImplementedException();
}
d1.Dispose();
d1
不被处理,d2
通常是。某些类型的异常可能会阻止using
块的处理,也可能会阻止一些程序崩溃。如果原因是电源故障或系统崩溃,您当然不能做任何事情。
发布于 2015-12-25 08:03:45
如果程序意外退出(例如,终止进程),则绝对不能保证调用IDisposable.Dispose
方法。这样的事情你最好不要依赖它。Dispose方法必须由代码手动调用,这不是CLR会自动为您调用的东西。
发布于 2015-12-25 10:02:29
除了Patrick和Alexei的答案之外,即使应用程序正确终止,清理也可能不会执行。
您可能知道,当垃圾收集器收集实现IDisposable
接口的对象时,不会调用IDisposable
方法。但是GC将调用Finalize
方法,也称为终结器。在其中,您应该使用处置模式编写清理逻辑。是的,.Net框架将尝试运行所有终结器,但没有保证它们将被执行。
作为一个例子,程序下面有非常长的运行终结者。因此,.Net将终止该进程,您将永远看不到消息。
class FinalizableObject
{
~FinalizableObject()
{
Thread.Sleep(50000);
Console.WriteLine("Finalized");
}
}
class Program
{
static void Main(string[] args)
{
new FinalizableObject();
}
}
这可能是由任何长时间运行的操作引起的,比如释放网络句柄或其他需要大量时间的操作。
因此,您不应该依赖终结器和一次性对象。但是所有打开的内核对象句柄都会自动关闭,所以您不应该担心它们。
我将建议您阅读一些关于终结器和GC的有趣文章,以及答案:
https://stackoverflow.com/questions/34464229
复制