当VisualStudio调试器退出时执行代码

16

我曾经以为,在终止调试时(例如按下“停止”按钮或按下Shift + F5),所有实现了finalizer或IDisposable接口的类都会被销毁。

我有一些实现了IDisposable接口的类。在应用程序从调试器(或在生产环境中崩溃)退出时,我想要尝试做一些事情。目前,Dispose()似乎没有被调用,也没有调用~MyClass(){}的finalizer方法。

有什么办法可以解决这个问题吗?


1
@Boo 已经明白了。但是,如果我能在至少一部分场景下运行代码,那就可以了。 - CoolUserName
在调试器中点击停止按钮就像操作系统终止您的应用程序一样。这是毫不客气和相当突然的,而且不考虑应用程序当前可能正在执行或打算执行的任何操作。 - Sam Axe
@Boo 这是一个 Windows 服务,在调试时作为一个基本程序运行,其中主线程具有一个无限循环 while(true){ Thread.Sleep(1000); }。 - CoolUserName
1
使用Ctrl+C终止程序,并确保您有一个处理程序来执行“Console.CancelKeyPress”以停止或关闭程序。 - Tergiver
还没有解决办法吗? - Revious
显示剩余5条评论
2个回答

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
就技术而言,“using” 只是一个 try/finally 的语法糖,因此它并不比常规的 finally 块更可靠。 - James Manning
1
是的,它是 try/finally(Dispose()) 的语法糖。在这里可以看到 - “using 语句确保即使在调用对象方法时发生异常,也会调用 Dispose 方法。您可以通过将对象放入 try 块中,然后在 finally 块中调用 Dispose 来实现相同的结果。”。http://msdn.microsoft.com/en-us/library/yh598w02%28v=vs.100%29.aspx - J. Ed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接