我曾经以为,在终止调试时(例如按下“停止”按钮或按下Shift + F5),所有实现了finalizer或IDisposable
接口的类都会被销毁。
我有一些实现了IDisposable
接口的类。在应用程序从调试器(或在生产环境中崩溃)退出时,我想要尝试做一些事情。目前,Dispose()
似乎没有被调用,也没有调用~MyClass(){}
的finalizer方法。
有什么办法可以解决这个问题吗?
我曾经以为,在终止调试时(例如按下“停止”按钮或按下Shift + F5),所有实现了finalizer或IDisposable
接口的类都会被销毁。
我有一些实现了IDisposable
接口的类。在应用程序从调试器(或在生产环境中崩溃)退出时,我想要尝试做一些事情。目前,Dispose()
似乎没有被调用,也没有调用~MyClass(){}
的finalizer方法。
有什么办法可以解决这个问题吗?
对于正常停止Windows服务,您应该将代码放在Stop方法中。
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.stop.aspx
一般情况下,粗鲁的线程中止和粗鲁的应用程序域卸载不会运行“正常”的终结器——您可以在此MSDN文章中获得更多详细信息。
到目前为止,我只是谈论了线程中止作为运行时在线程上抛出ThreadAbortException的结果。通常,这将导致线程终止。但是,线程可以处理线程中止,防止其终止线程。为了解决这个问题,运行时提供了一个更强大的操作,名为粗鲁的线程中止。粗鲁的线程中止会使线程停止执行。当这种情况发生时,CLR不保证线程上的任何回退代码都会运行(除非代码在CER中执行)。确实很粗鲁。
同样地,尽管典型的应用程序域卸载将优雅地中止域中的所有线程,但粗鲁的应用程序域卸载将粗暴地中止域中的所有线程,并且不保证与该域中的对象相关联的正常终结器将运行。 SQL Server 2005是使用粗鲁的线程中止和粗鲁的应用程序域卸载作为其升级策略的CLR主机之一。当发生异步异常时,资源分配失败将升级为线程中止。当线程中止发生时,如果它没有在SQL Server设置的时间跨度内完成,则会升级为粗鲁的线程中止。同样地,如果应用程序域卸载操作没有在SQL Server设置的时间跨度内完成,则会升级为粗鲁的应用程序域卸载。(请注意,刚才提出的策略并不完全是SQL Server使用的策略,因为SQL Server还考虑了代码是否在关键区域中执行,但稍后会详细介绍这个主题)。
CLR并不保证何时收集或处理您的对象。
您可以尝试显式调用垃圾回收器,但我认为这不是推荐的方法。
最好的方法是在using
块中使用IDisposable
对象。
只有在这种情况下,您才能确保它们何时被处理。