2011-07-19 56 views
2

我正在將DataTable存儲在ASP .NET Cache屬性中。可以對數據表進行操作:DataTable和線程安全

  • 結合網格控制(即第三方電網內部管理數據源對象,回傳後的數據源是空的,我認爲,一旦數據綁定它不使用數據源數據表中的任何更多)
  • 去除數據錶行(Row.Delete()

我加入時對DataTable實例明確工作基本讀/寫鎖,但我不知道有沒有與任何其他線程安全問題解決方案,我想在網格時可能會出錯控件位於DataBinding的中間,其他線程刪除行?如果是這樣,我怎樣才能同步訪問該表,以便沒有刪除方法調用時,網格控制綁定?是否有任何事件組合,我可以把AcquireWriterLock & ReleaseWriterLock方法?

謝謝你,帕維爾

回答

2

如果你暴露通過數據綁定,然後忘記它的數據表;你不能使線程安全。即使你以某種方式包裝了DataView(在自定義ITypedList中),那也做得不夠 - 數據綁定會對數據做出假設,特別是IList等 - 例如,它不會隨機更改長度在迭代數據或在UI線程中添加行的過程中採用線程爭用的方式。

規定通過事件在同一線程上的變化...但是不交線程。

+0

謝謝!如何更改列值?它是否也會導致問題?我可以添加列IsDeleted,並且不會渲染具有該標誌集的行。 – dragonfly

+0

@dragonfly但是,你最有可能最終會從非UI線程中引發事件,綁定將嘗試對非線程做出反應 - 再次在非UI線程中。這反過來很可能會做壞事。 –

+0

不是個好消息。那麼如何以安全的方式實現緩存.....? DataTable.Copy()並在該副本上進行綁定? – dragonfly

0

正如在其他的答案中提到的人:

  • 一般只緩存不變的數據(或至少是:把它當作一成不變的,一旦它的存在)。否則,它是不是一個緩存
  • 如果有人曾經打算編輯
  • 如果你暴露通過數據綁定,然後忘記它的數據表請勿使多個請求的公共數據;你不能使線程安全

但是,我真的需要緩存一個數據表。理由:

  • 查詢得到的結果真的很大&費時。此外,使用該查詢撥打電話的頁面刷新率也很高。因此,數據庫引擎變得bussy。隨着緩存,我會得到每2分鐘只有1分貝引擎呼叫
  • 該查詢的結果不同。但用戶看到相同的結果,比如2分鐘,完全可以接受。因此將數據存儲在緩存中2分鐘是可以接受的。也沒有其他問題像併發,樂觀/悲觀離線鎖...

然而,當用戶在它看到的數據進行操作,有些變化是對數據的:

  • 這種改變必須是應用於數據庫。在執行緩存之前,在更改爲db之後,應用程序再次發出巨大查詢以獲得僅有細微差異的結果
  • 現在,通過緩存,更改應用於數據庫並應用於緩存的數據表。然後,該數據表再次綁定到數據綁定控制。優點:無需進行調用WCF使用Web應用程序

巨大的查詢+傳輸的數據表我這是怎麼實現的鎖定該解決方案獲取數據:

  1. 緩存的數據存儲在單例像包裝:

    public class AllocationQueue 
    { 
        private static object tableSyncRoot = new object(); 
    
  2. 這是修改緩存DataTable的代碼唯一片:

    internal void RemoveTaskRowFromAllocationQueue(Guid queueId, Guid taskId) 
    { 
        var allocationQueueEntry = GetAllocationQueueEntry(queueId); 
        var queueData = allocationQueueEntry.TaskIdIndexedView; 
        lock(tableSyncRoot) 
        { 
         int rowIndex = queueData.Find(new object[] { taskId }); 
         queueData[rowIndex].Delete(); 
        } 
    } 
    
  3. 這是唯一的一段代碼,暴露的數據綁定數據:

    public DataTable GetAllocationQueue(Guid queueId, string filter) 
    { 
        var allocationQueueEntry = GetAllocationQueueEntry(queueId); 
        lock (tableSyncRoot) 
        { 
         var rows = allocationQueueEntry.Table.Select(filter); 
         if (rows.Length > 0) 
         { 
          return rows.CopyToDataTable<DataRow>(); 
         } 
        } 
        return null; 
    } 
    

線程安全&的作品就像一個魅力(我說得對不對? :))。但是對我的要求非常特別。