2016-01-22 37 views
1

我注意到有MSDN上有一個Disposing事件有以下評論(like this one)一些類:如果Dispose()被Finalizer調用,您能否觸發「Disposing」事件?

時發生調用Dispose或當該對象被定稿,並通過垃圾收集器收集。

我想在我的一個類中實現我自己的Disposing事件。這是我的基本實現(following the best practices for the dispose pattern):在我的代碼審查

public abstract class Handle : IDisposable 
{ 
    public bool Disposed { get; private set; } 

    public event System.Action DisposingCompleted; 

    public Handle() 
    { 
     Disposed = false; 
    } 

    ~Handle() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing = false) 
    { 
     if (Disposed) 
     { 
      return; 
     } 

     if (disposing) 
     { 
      HandleManagedResources(); 
     } 

     HandleUnManagedResources(); 

     Disposed = true; 

     if (DisposingCompleted != null) 
     { 
      DisposingCompleted(); 
     } 
    } 

    protected virtual void HandleManagedResources() {} 
    protected virtual void HandleUnManagedResources() {} 
} 

有人提到,他們不知道應該像這樣的事件是否射擊是安全的,因爲Dispose()可能會從終結調用,但是,根據對於我在頂部添加的MSDN鏈接的評論,很明顯,有些對象會在事件處置或定稿時觸發事件。

我錯過了什麼,或者這是安全的嗎? GraphicsDevice如何實現從處置或最終確定時觸發的事件?如果答案只是「不,你不能做到這一點」,那麼是否有其他方式達到相同的效果? (用於物體的事件被設置OR定稿)

+0

您應該使用標準的建議實現和模式,如命名和約定,而不是自己滾動。特別是,你應該使用'bool disposing'而不是'fromFinalizer'。 –

+0

@ LasseV.Karlsen當然,我改變了名字。 – Foggzie

+0

您可能想要閱讀Eric Lipperts的文章,瞭解可在定稿器中發生的所有奇怪現象http://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/ – juharr

回答

2

如果你打算做任何涉及在Dispose方法的其他對象只應做,當Dispose顯式調用,而不是當它是從所謂的終結。

其原因是,如果該其他對象也符合資格收集,則不能保證該對象尚未最終確定。

+0

那麼當Dispose被調用或者當這個對象被最終化時,如何讓像鏈接的'GraphicsDevice'有一個事件被激發?如果我能保證訂閱者的壽命長於發佈者,該怎麼辦? – Foggzie

+1

您可以輕鬆編寫代碼來完成它,但不建議,也不一定安全。 –

+0

所以我很困惑它是如何通過微軟已經實現的類來實現的。我發現很難相信XNA框架中內置的功能,比如'GraphicsDevice'和'StorageContainer',都可以這樣做,但是不要指出那些事件不安全的地方。如果答案只是「不,你不能做到這一點」,那麼是否有其他方式達到相同的效果? – Foggzie

相關問題