2014-10-30 27 views
3

以下是有關這我不清楚一個例子:如何正確處理來自終結器的非託管資源的收集?

public class SomeClass : IDisposable { 

    ~SomeClass() { 
     Dispose(false); 
    } 

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

    private bool _disposed; 

    protected virtual void Dispose(bool disposing) { 
     if (!_disposed) { 
      if (disposing) { 
       // TODO: Release any managed resources here... 
      } 

      // ?! Is it safe to enumerate the dictionary here ?! 
      foreach (var resource in _resources.Values) 
       ReleaseBuffer(resource); 
      _resources = null; 

      _disposed = true; 
     } 
    } 

    private Dictionary<string, IntPtr> _resources; 

    ... 

} 

會不會是安全的枚舉管理字典,以釋放非託管資源?

由於未定義終結器的順序,因此字典的可用性是否不確定?

這裏是從MSDN截取的報價,我感到迷惑[1]:即使一個對象指的是

  • 兩個對象的終結不能保證在任何特定的順序運行,其他。也就是說,如果對象A具有對象B的引用並且都具有終結器,則在對象A的終結器開始時,對象B可能已經完成。
  1. http://msdn.microsoft.com/en-us/library/system.object.finalize(v=vs.110).aspx
+1

它應該是安全的,字典是一個管理對象,根植於您的類的實例,它將被訪問,直到調用終結器。請參閱http://stackoverflow.com/questions/13954829/gc-collect-and-finalize。 – galenus 2014-10-30 19:42:24

+2

'Dictionary'沒有終結符。所以你很安全。 – Blorgbeard 2014-10-30 19:43:41

+2

@Blorgbeard:字典不是線程安全的,對於運行終結器的線程上下文沒有任何保證。 – supercat 2014-10-31 20:24:27

回答

2

而不是有一個非託管資源字典,我會建議有一個獨立的包裝對象的字典,其中每個負責保護一個非託管資源。如果持有該字典的對象被放棄並且包裝對象不存在其他引用,則所有包裝對象都將被終止,而不需要在該過程中涉及字典本身。使用這種方法可以更容易地處理在對象構建過程中發生異常的情況,並且至少在某種程度上理解了一個對象發現自己在被終止排隊的時間和終結器的時間之間復活的情況運行[在這種情況下,代碼一般不能期望「正確運行」,但應避免破壞系統其餘部分的狀態]。例如,使用句柄的代碼在使用過程中可能會獲取鎖,並且在使用後檢查「disposeObjectASAP」標誌;如果設置,重新獲得鎖和處置對象。終結器本身應該設置標誌,然後嘗試獲取鎖定;如果它成功獲得鎖定,則應該處理該對象。如果不行,它設置標誌的事實應該暗示有鎖的代碼註定要檢查標誌並清理對象,所以終結器不必。如果終結器過早運行,它可能釋放另一個線程將需要的資源,導致該另一個線程上的操作失敗,但終結器不會釋放資源,而另一個線程正在使用它們或處置它們,因爲釋放那些資源情況可能導致大規模的系統損壞

0

Implementing a Dispose method,你看那裏是不是安全的代碼。

的代碼示例顯示:

protected virtual void Dispose(bool disposing) 
{ 
    if (disposed) 
     return; 

    if (disposing) { 
     // Free any other managed objects here. 
     // 
    } 

    // Free any unmanaged objects here. 
    // 
    disposed = true; 
} 

你的樣品顯示您在條件塊釋放非託管資源。 MSDN示例顯示您應該在條件塊中釋放管理的資源。

,因爲它說的文本(標題「的Dispose(布爾)過載」下):

如果方法調用來自一個終結(即,如果處置是false),只釋放非託管資源的代碼將執行。由於未定義垃圾收集器在最終化​​過程中銷燬託管對象的順序,因此調用Dispose重載的值爲false可防止終結器嘗試釋放可能已被收回的託管資源。

+0

我的'if(disposing)'語句裏的註釋完全是一個錯字。但是打算訪問'_resources'集合。爲了將來的清晰度,我已經在我的問題中糾正了這個錯字。謝謝 – 2014-10-30 21:36:13

相關問題