2013-03-28 57 views
-1

我有一個通用的緩存訪問方法在一個帶有三個參數的單例類中。C#將鎖對象傳遞到通用緩存訪問方法

  1. 委託(不帶參數void返回類型)
  2. 高速緩存標籤
  3. 旨在阻止併發緩存設置

見下面的鎖定對象:

protected delegate T GetDataMethod<T>(); 


protected override D GetCachedData<D>(GetDataMethod<D> dataAccessMethod, string cachelabel, object lockObject) 
    { 

     if (MemoryCache.Default[cachelabel] == null) 
     { 
      lock (lockObject) 
      { 
       //Inside the lock, test once again in case the cache object has been set already 
       if (MemoryCache.Default[cachelabel] == null) 
       { 
        umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -10, cachelabel + " inside lock, cache empty"); 

        D data = default(D); 


         try 
         { 
          data = dataAccessMethod(); 
         } 
         catch (Exception ex) 
         { 

          //Logging        
         } 



        MemoryCache.Default.Add(cachelabel, data, GetCacheItemPolicy()); 
       } 
      } 
     } 

     return (D)MemoryCache.Default[cachelabel]; 
    } 

每個數據集合都有單獨的鎖對象,它們將緩存設置爲靜態只讀對象。然而,通過將它們傳遞給方法,它們的作用域只存在於方法中,所以鎖定變得無關緊要。

我不能使用'ref',因爲你無法通過ref傳遞一個靜態對象,因爲周圍的類是單例,如果我使得鎖對象不是靜態的,它會影響嗎?如果會,任何人都可以推薦一種更好的方式來處理它,而不使用基於cacheLabel的switch語句?

編輯: 只是爲了清楚起見,該方法足跡:

protected override D GetCachedData<D>(GetDataMethod<D> dataAccessMethod, string cachelabel, ref object lockObject) 

將無法​​正常工作,鎖定的對象是靜態的。我猜這個問題真的是 - 在一個單例中,鎖對象需要是靜態的才能成爲線程安全的? (是的,這是一個線程安全的單身人士)

+2

對你的緩存使用ConcurrentDictionary將緩解你http://msdn.microsoft.com/en-us/library/dd287191.aspx除非你的問題只是一個思維練習。 –

+1

'它們的作用域只存在於方法內::你的鎖對象是引用類型不是它們嗎?如果是這樣,你能解釋一下你的意思嗎? –

+0

感謝迄今爲止的評論傢伙。你不能通過ref傳遞一個靜態對象,如果我刪除靜態聲明,是不是否定了鎖對象的點?或者,鑑於該方法是在一個單身的否定否定... 這不僅僅是一個思想練習,MemoryCache對象的setter不是線程安全的(就像我發現自己的痛苦),並且數據請求需要花費相當多的時間通過EF,所以我需要鎖定setter方法來防止多個線程填充各種緩存項目(因此兩個階段檢查 - 一次在鎖定之前,一次在鎖定之內) –

回答

1

我認爲你錯過了ref關鍵字 - 你不需要它。您傳遞的是已經是參考類型的object。添加ref關鍵字將使其成爲參考的參考。

+0

對於這個問題的道歉,沒有足夠的咖啡,並花費太多的時間看着相同的8行代碼關閉了我的大腦...... –