2010-08-11 55 views
47

可能重複:
How does one tell if an IDisposable object reference is disposed?如何檢查對象已被釋放在C#

是否有檢查對象已被釋放不同的,那麼

try 
{ 
    myObj.CallRandomMethod(); 
} catch (ObjectDisposedException e) 
{ 
    // now I know object has been disposed 
} 
的方法

在我的情況下,我使用的TcpClient類有Close()方法配置對象並且這會發生在我沒有控制的代碼片段中。在這種情況下,我想有更好的解決方案,然後捕捉異常。

+3

http:// stackoverflow。com/questions/192206/how-do-one-tell-if-an-idisposable-object-reference-is-dispos – w69rdy 2010-08-11 10:55:56

+0

我知道這個問題一般來說太常見了,因爲沒有在stackoverflow上進行問答,但我沒有搜索到它。 – jethro 2010-08-11 12:01:02

回答

29

一個好方法是從TcpClient的派生並重寫處分權(布爾)方法:

class MyClient : TcpClient { 
    public bool IsDead { get; set; } 
    protected override void Dispose(bool disposing) { 
     IsDead = true; 
     base.Dispose(disposing); 
    } 
} 

其中獲如果其他代碼創建了實例,則不起作用。然後你必須做一些絕望的事情,比如使用Reflection來獲得私有m_CleanedUp成員的值。或者趕上例外。

坦率地說,沒有一個可能會達到很好的結果。你真的沒有想寫入到TCP端口。但是你不會控制你的代碼,你無法控制的那些錯誤的代碼現在可以控制你的代碼。你已經增加了bug的影響。與該代碼的所有者交談並解決問題是迄今爲止最好的解決方案。

14

如果您不確定對象是否已處置,您應該調用Dispose方法本身,而不是像Close這樣的方法。儘管框架並不能保證Dispose方法必須在沒有異常的情況下運行,即使對象之前已經被拋棄了,它也是一個常見的模式,並且據我所知,在框架中的所有可丟棄對象上都有實現。

Dispose典型模式,按照Microsoft

public void Dispose() 
{ 
    Dispose(true); 

    // Use SupressFinalize in case a subclass 
    // of this type implements a finalizer. 
    GC.SuppressFinalize(this);  
} 

protected virtual void Dispose(bool disposing) 
{ 
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource. 
    if (!_disposed) 
    { 
     if (disposing) { 
      if (_resource != null) 
       _resource.Dispose(); 
       Console.WriteLine("Object disposed."); 
     } 

     // Indicate that the instance has been disposed. 
     _resource = null; 
     _disposed = true; 
    } 
} 

通知上_disposed檢查。如果您要調用實現此模式的Dispose方法,則可以根據需要多次調用Dispose而不觸發異常。

+2

這沒有幫助。該成員是私人的。 – 2010-08-11 11:07:52

+0

對不起,我可能誤讀了你的問題。你是否正在尋找是否因爲「我應該處理這個對象」以外的原因而處理對象?如果是這樣,爲什麼?具有未知代碼可能會丟棄對象看起來像是一個漏洞設計。 – 2010-08-11 11:09:26

+2

雖然框架本身並沒有給出任何保證,但是IDisposable的文檔說明了這一點:*「如果一個對象的Dispose'方法被多次調用,對象必須在第一次調用之後忽略所有的調用。如果多次調用Dispose'方法,則不會拋出異常。Dispose'以外的實例方法在已經處理資源時可以拋出ObjectDisposedException異常。「* http://msdn.microsoft.com/en-us/ library/system.idisposable.dispose.aspx – LukeH 2010-08-11 11:23:48

15

可靠的解決方案是捕獲ObjectDisposedException。

因爲在調用Dispose方法的線程和訪問對象的線程之間存在競爭條件,所以編寫Dispose方法的重寫實現的解決方案不起作用:在檢查了假設的IsDisposed屬性之後,對象可以真正處置,拋出異常都一樣。

另一種方法可能是暴露一個假設事件Disposed(如this),用於向每個感興趣的對象通知處置對象,但這可能難以根據軟件設計進行規劃。