2013-02-03 31 views
2

我有一個類MyClass。這個類有一個字段:public ReaderWriterLockSlim rw;(更簡單的示例代碼公開)。許多線程可以使用rw.EnterReadLockIDisposable和ReaderWriterLockSlim

而且我已經實現IDisposable接口讀取MyClass數據:

private void Dispose (bool pDisposing) 
{ 
    { 
     if (pDisposing) // release managed resources 
     { 
      if (rw != null) 
      { 
       rwLockSlim.Dispose(); 
       rwLockSlim = null; 
      } 
     } 

     //--- release unmanaged resources 
     // some code... 
     isDisposed = true; // ... 
    } 
} 

就像你看到的,當一個線程使用MyClass問題是,當MyClass的對象上第二個線程調用Dispose。我不能配置ReaderWriterLockSlim,因爲它會使我的應用程序崩潰。那麼我應該刪除那些釋放託管資源的行?無論如何,ReaderWriterLockSlim將在不久的將來由GC收集,對吧? (但這類資源昂貴嗎?)。
也許我應該在Dispose metod中添加一些鎖(syncObject)或其他東西?

編輯:我也處理AllocHGlobal,所以我需要等待,直到所有線程將停止讀取/寫入到myClass

不同的觀點:

public MyClass : IDisposable 
{ 
      public void EnterReadLock(); // calls rwLockSlim.EnterReadLock, 
              // if object is disposed throws Exception 

      public void ExitReadLock(); // same as above 

      public void Dispose();  // wait until all threads exit from locks, 
              // frees unamanged resources, mark class as disposed 
} 

回答

1

這可能不是最好的答案,而觀察和一些想法。

你能簡化你的代碼嗎?我的意思是,其他類型不應該在乎你的類型是否在特定的併發條件下拋出異常。你將如何測試這個?公共鎖定對象是邪惡的。它必須是私人的,除非你想花費數月試圖找出神祕的錯誤。

如果調用dispose方法,這意味着沒有其他對象應該使用此對象。這意味着在調用dispose方法之前,必須首先確保所有線程在對象上完成操作。

建議

  • 請鎖定私人
  • 確保所有線程都完成,要求處置
  • 添加超時安全行爲之前
  • 考慮使用靜態鎖定對象
  • ReaderWriterLockSlim是不是資源昂貴(到你應該關心你的應用程序)
  • 如果您的課程使用一次性資源,那麼實施IDisposable並處置需要處理的成員通常會更好。
  • 不要在Dispose方法中添加任何鎖,它應該很簡單。這可能會引入不愉快的錯誤。因爲如果您忘記手動調用Dispose,它將被GC非確定性地調用(通過finiliser,您應該添加以調用Dispose)
  • 正確的方法是等待所有線程完成並處理一個對象
+0

公衆ReaderWriterLockSlim僅用於示例目的。就像你在第二個例子中看到的,我做了一個方法EnterReadLock(),它調用了rwLockSlim.EnterReadLock()。無論如何感謝您的答案中的所有建議。 – zgnilec

+0

我也會盡量避免這樣的構造。從我可以告訴它看起來像你在多個線程中使用'MyClass'類的單個實例,這很好。但是,如果你這樣做,然後使方法線程安全,不要依賴其他代碼正確執行'EnterReadLock'和'ExitReadLock'。 – Dirk

+0

在某些情況下,我們希望在調用Dispose之前等待線程完成,但是有一些阻塞API(用於通信等),其中Dispose是可以在對象上調用的* only *方法正在等待某些事情發生(在某些硬件設備上,一旦請求了操作,如果不將設備置於無法使用的狀態,直到設備重新配置),則無法取消該設備。在這種模式下,對繁忙的對象調用「Dispose」會導致正在進行的操作拋出異常。 – supercat