2015-12-15 15 views
2

以下方法通過等待已經運行的操作的結果來處理併發請求。如何使用內存緩存的定時器觸發一個方法?

數據請求可能與同一/不同憑據同時進入。對於每組唯一的憑證,最多隻能有一個GetCurrentInternal呼叫正在進行,其中一個呼叫的結果在準備就緒時返回給所有排隊的服務員。

private readonly ConcurrentDictionary<Credentials, Lazy<Data>> _dataToCredentialMap = 
     new ConcurrentDictionary<Credentials, Lazy<Data>>(); 

public virtual Data GetCurrent(Credentials credentials) 
{ 
    if (credentials == null) { return GetCurrentInternal(null); } 

    // It will only allow a single call to GetCurrentInternal, even if multiple threads query its Value property simultaneously. 
    var lazyData = new Lazy<Data>(() => GetCurrentInternal(credentials)); 

    var data = _dataToCredentialMap.GetOrAdd(credentials, lazyData); 
    return data.Value; 
} 

而且我在構造函數中添加了timer這個類。這是基於時間的無效策略,其中高速緩存條目在一段明確定義的時間段後自動失效。

_dataUpdateTimer = new Timer(UpdateData, null, TimeSpan.Zero, _dataUpdateInterval); // 1 min 

方法更新數據如下所示:

private void UpdateData(object notUsed) 
{ 
    try 
    { 
     foreach (var credential in _dataToCredentialMap.Keys) 
     { 
      var data = new Lazy<Data>(() => GetCurrent(credential)); 
      _dataToCredentialMap.AddOrUpdate(credential, data, (k, v) => data); 
     } 
    } 
    catch (Exception ex) 
    { 
      _logger.WarnException(ex, "Failed to update agent metadata"); 
    } 
} 

我想使用的.Net MemoryCache類insted的我ConcurrentDictionaryTimer,來更新我的Credential and Data我認爲這將是更有效。

我知道如何使用MemoryCache而不是ConcurrentDictionary,但是如何在沒有Timer的構造函數中每分鐘撥打UpdateData

你能幫我請怎麼做嗎?

+0

只需使用Set/AddOrGetExisting()重載即可傳遞DateTimeOffset。 DTO指定物品何時被驅逐,您的計時器所做的同樣的事情。 –

+0

MemoryCache不支持確保每個鍵只創建一個值。你現有的方法很好。 – usr

+0

@usr所以我可以依靠'ConcurrentDictionary'只有一個線程可以'GetOrAdd'某個鍵/值,但是如果我將這一行更改爲MemoryCache.Default.AddOrGetExisting(...)它會是一個錯誤? – Anatoly

回答

1

您可以在沒有定時器的情況下使用MemoryCache執行此操作。只需將CacheItemPolicy設置爲AbsoluteExpiration:

MemoryCache memCache = MemoryCache.Default; 
memCache.Add(<mykey>, <myvalue>, 
      new CacheItemPolicy() 
      { 
      AbsoluteExpiration = DateTimeOffset.Now.Add(TimeSpan.FromMinutes(_expireminutes)), 
      SlidingExpiration = new TimeSpan(0, 0, 0) 
      } 
     ); 
+0

我的'_dataUpdateTimer'每分鐘都會調用'UpdateData'。在'UpdateData'裏面我更新我的字典。你的代碼如何與'MemoryCache'一起做同樣的事情? – Anatoly

+0

您可以對緩存項目的evict事件做出反應 – Peter

相關問題