我正在开发的.NET相当广泛的系统,它涉及到很多系统编程的。 大多数时间,我使用了IDisposable模式来处理资源的处置,但有时这是不适用(或错误地离开了)和资源被最终确定期间被毁()。 这可能会在COM时,析构函数调用Dispose()发生互操作,或者和有它内部的一个例外。
基本上是:它并不总是能够清楚地看到和处理每个场景时终结可能抛出。 而当它发生时,应用程序肯定会崩溃。
为什么我关心的是具体这类问题的原因是,终结器不是由创建或使用对象的线程调用,所以它几乎是不可能完成的任务异常配合在其中创建对象的上下文。 所有你得到一些通用的GC线程。
所以,现在的问题给公众 :如果你考虑这些类型的问题,你会怎么做来控制它们? 标签的对象? 使用第三方工具,它允许跟踪那些问题?
另外:是否有可能引发某种全球性的“终结扔”事件,至少记录,这非常的问题发生了什么?
EDIT1:非常感谢大家谁提交的宝贵意见,我想我更为清楚现在需要做什么。 最后一件事我真的想从这个讨论中得到的是,如果有人知道的方法来触发代码的例外终结(即使应用程序崩溃仍然是不可避免的),这样我至少可以记录它,而不必修改的每一个析构函数类。
终结时,才需要.NET中的直接拥有的非托管资源(即不仅通过了IDisposable成员)班。 使用标准模式作为MSDN描述的这种类必须实现IDisposable。
终结应该永远只能处置非托管资源-通常的模式是调用一个方法“保护无效的Dispose(BOOL处置)”设置为false的配置参数。
这种方法通常被实现是这样的:
protected void Dispose(bool disposing)
{
if (disposing)
{
// Dispose managed resources here.
// (e.g. members that implement IDisposable)
// This could throw an exception, but will *not* be called from the finalizer
...
}
... Dispose unmanaged resources here.
... no need for any exception handling.
... Unlikely to get an exception, and if you do it will be fatal.
}
既然你永远只能处置非托管资源,你一般不应该引用任何管理的对象,不应该需要包括任何异常处理。
你的问题是基于一个错误的有些前提,那就是它无法处理的每个场景,其中一个终结可能会抛出。 这正是你需要在这里实现什么。 终止过程中出现的异常将终止进程。 除非例外是真正致命的,在这种情况下让程序崩溃,你应该处理此异常,不会崩溃的程序的方式。
有一个终结罚球几乎是具有C ++的析构函数抛出的那样糟糕。 IDisposable接口调用的大多数实现转化为主动(IDisposable.Dispose())和被动(终结器线程)同样的方法处理操作。 如果终结版本扔那么它可能或可能是积极的处置可以奉送。 此,很象C ++的析构函数投掷,将防止在某些情况下正确地布置的嵌套资源。
不允许,除非他们是真正致命的,你的应用程序异常,从一个终结传播。
我做我的班以下,所以在调试版本,我可以尝试捕获这些类型的东西。
在调试版本,一个断言做是为了保证类是显式地布置。 另一个断言做是为了确保终结不会抛出。 在发行/制作版本,此检查不执行到更高的性能。
C#代码
using System;
using System.Diagnostics;
namespace ConsoleApplication8
{
class Program
{
class IReferenceUnmanagedMem : IDisposable
{
#if(DEBUG)
private static readonly string _ctorStackTrace = Environment.StackTrace;
#endif
public IReferenceUnmanagedMem()
{
}
~IReferenceUnmanagedMem()
{
#if(DEBUG)
Debug.Fail("Dispose method not called.", _ctorStackTrace);
try
{
#endif
Dispose(true);
#if(DEBUG)
}
catch(Exception e)
{
Debug.Fail("Dispose method threw exception in finalizer.", e.ToString());
}
#endif
}
public void Dispose()
{
Dispose(false);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool inFinalizer)
{
if(inFinalizer)
{
throw new Exception("I Know, this is a no-no.");
}
}
}
public static void Main()
{
IDisposable disposable = new IReferenceUnmanagedMem();
disposable = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
Apache的DBCP,用废弃的连接问题时,似乎当打开一个连接,以便存储堆栈跟踪吐出来时,它清除连接生成异常。 对于那些没有被正确配置资源,你可以尝试使用这样的技术来追踪资源如何初始化和使用,使finalize方法能够产生有用的错误输出。
文章来源: Exceptions during Finalize(): what methodology are you using to detect garbage collector-time exceptions?