2012-07-13 103 views
12

我曾经假定当终止调试时(例如通过点击停止按钮或按Shift + F5),任何实现终结器或IDisposable的类都将被处置。当VisualStudio调试器正在退出时执行代码

我有一些类实现IDisposable。在应用程序从调试器中退出时(或者在生产中崩溃),有几件事情我想要(尝试)并做。现在,Dispose()似乎不会被调用,也不是终结器~MyClass(){}

有没有办法做到这一点?

+0

除非崩溃是由可捕获的异常引起的,否则不能保证运行后崩溃的任何代码。这是应用程序崩溃的本质。出了问题,现在你的流程被强行终止了。 – 2012-07-13 21:21:49

+1

@Boo了解。但是,如果我可以在至少一部分场景下运行代码,那么我会采取这种做法。 – CoolUserName 2012-07-13 21:22:26

+0

在调试器中点击停止按钮与终止您的应用程序的操作系统相同。它突然间毫不客气,相当枯燥,不考虑应用程序可能正在做什么或打算做什么。 – 2012-07-13 21:23:10

回答

2

对于Windows服务的正常停止,您应该将代码放在Stop方法中。

http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.stop.aspx

一般来说,粗鲁的线程中止和粗鲁的应用程序域卸载不会运行“正常”的终结 - 你可以MSDN文章中得到更多的细节。

https://web-beta.archive.org/web/20150423173148/https://msdn.microsoft.com/en-us/magazine/cc163716.aspx

到目前为止,我只是谈到线程中止为运行在一个线程抛出ThreadAbortException的结果。通常,这会导致线程终止。然而,一个线程可以处理一个线程中止,阻止它终止线程。为了解决这个问题,运行时提供了一个更强大的动作,即适当命名的粗线程中止。粗鲁的线程中止导致线程停止执行。发生这种情况时,CLR不保证线程上的任何退出代码将运行(除非代码在CER中执行)。粗鲁,确实。

同样,虽然典型的应用程序域卸载将优雅地中止域中的所有线程,但粗鲁的应用程序域卸载将粗暴地中止域中的所有线程,并且不保证与该域中的对象关联的正常终结器将运行。 SQL Server 2005是一个CLR主机,它利用粗暴的线程中止和粗暴的应用程序域卸载作为其升级策略的一部分。发生异步异常时,资源分配失败将升级为线程中止。当线程中止发生时,如果它没有在SQL Server设置的时间范围内完成,它将被升级为粗线程中止。同样,如果应用程序域卸载操作未在SQL Server设置的时间范围内完成,则会升级到粗鲁的应用程序域卸载。 (请注意,刚刚制定的策略并不完全是SQL Server使用的策略,因为SQL Server也考虑到代码是否在关键区域执行,但更多关于该主题的内容很短)。

1

那么,CLR并没有就你的物品什么时候被收集或处置做出任何承诺。

您可以尝试显式调用垃圾回收器,但我不认为这是推荐的方法。

最好的办法是在using块内使用IDisposable对象。
这是您保证他们将被处置时的唯一时间。

+2

FWIW,'using'只是一个try/finally语法糖,所以它不会比普通的finally块更有保证。 – 2012-07-14 06:05:12

+0

是的,它是try/finally(Dispose())的语法糖。请参阅这里 - “使用语句确保即使在对对象调用方法时发生异常,也可以调用Dispose,通过将该对象放入try块中,然后在finally块中调用Dispose,可以实现相同的结果。 http://msdn.microsoft.com/en-us/library/yh598w02%28v=vs.100%29.aspx – 2012-07-14 10:22:40

相关问题