什么时候不能使用SafeHandle而不是Finalizer / IDisposable?

时间:2011-11-13 08:50:24

标签: c# dispose idisposable finalizer

当看到整个终结者/ IDisposable问题时,通常会看到,最后,经过所有长篇描述后,会有一些含义为“LOL我所说的实际上没用,你应该使用SafeHandle改为再见!“ 所以我想知道SafeHandle在什么情况下不合适,这样你就不得不求助于终结者/ IDisposable旧方式?

3 个答案:

答案 0 :(得分:3)

  

什么时候不能使用SafeHandle而不是Finalizer / IDisposable?

显而易见的答案几乎从不,Safehandles提供了很多优势。

ReleasHandle()中的代码必须确认Constrained Execution Region (CER)的约束。它可以(应该)不调用可能抛出或锁定的代码。因此,如果您的清理更复杂且“不可靠”,您仍然必须使用Finalizer /析构函数。

但对于(OS)句柄,您可以而且应该始终使用SafeHandle。

答案 1 :(得分:3)

显然,当您正在包装的非托管资源未通过句柄获取时。这是罕见的,但并非闻所未闻。一个例子是用C ++ / CLI代码编写包装器,通常用于包装本机C ++类。然后资源是内存。没有管理的那种。

尽管如此,您可以在职业生涯中编写托管代码,而永远不会编写终结器。终结器属于框架类。

答案 2 :(得分:0)

许多类型的非托管资源可以通过在句柄上使用简单的API调用来满足其清理职责。这些资源可以(并且通常应该)有效地封装在SafeHandle中。一些其他类型的非托管资源(例如,由长期存在的发布者持有的事件订阅)具有清理职责,这些职责不能通过终结器来处理。如果语义无用的强引用使被遗弃的对象保持活动,则终结器可能是无用的,并且可能无法使用必须由创建它们的线程清理的资源。没有必要为这些资源编写自定义终结器,因为没有任何类型的终结器可以消除确保它们确定性处理的绝对100%的必要性。

但是,某些类型的资源可能会受益于终结器,即使他们需要执行约束执行区域内不允许的操作。终结器在后台线程负责操作对象的情况下可能很有用,并且主应用程序持有一个对象,而该对象又持有对真实对象的引用。主应用程序的引用保持对象上的终结器可以向后台线程发信号通知它不再需要它所维护的对象。必须仔细进行此类信号传输以确保它不会破坏终结器线程,但如果小心操作,即使在CER中不允许将其放入终结器中也可能会有所帮助。