我正在處理一項服務,該服務負責記錄發送到我們服務的請求。該服務正在脫機工作(正在被解僱和忘記)。 我們正在根據一些輸入參數(產品ID)將請求保存到不同的數據庫。我們不希望每次有人提出請求時都保存到數據庫中 - 我們寧願建立一些「批次」來插入,並且每N
時間(比如10秒)執行InsertMany
。我已經開始實施,現在我掙扎了大約2件事:C#Concurent dictionary - 鎖定值
- 我需要使用
ConcurrentDictionary
嗎?看起來我會達到相同的正常字典 - 如果對上述答案是「不,在你的情況下沒有從
ConcurrentDictionary
的好處」 - 有沒有辦法重新寫我的代碼「正常」使用ConcurrentDictionary
所以我可以避免使用鎖定並確保AddOrUpdate
不會與清除批次發生「衝突」?
讓我貼的片段,並進一步解釋:
// dictionary where key is ProductId and value is a list of items to insert to that product database
ConcurrentDictionary<string, List<QuoteDetails>> _productDetails;
public SaverService(StatelessServiceContext context)
: base(context)
{
_productDetails = new ConcurrentDictionary<string, List<QuoteDetails>>();
}
// this function will be fired and forgotten by the external service
public async Task SaveRecentRequest(RequestOptions requestData, Response responseData)
{
await Task.Run(() => {
foreach (var token in requestData.ProductAccessTokens)
{
// this function will extract the specific product request (one request can contain multiple products)
var details = SplitQuoteByProduct(requestData, responseData, token);
_productDetails.AddOrUpdate(token, new List<QuoteDetails>() { details }, (productId, list) =>
{
list.Add(details);
return list;
});
}
});
}
// this function will be executed by a timer every N amount of time
public void SaveRequestsToDatabase()
{
lock (_productDetails)
{
foreach (var item in _productDetails)
{
// copy curent items and start a task which will process them
SaveProductRequests(item.Key, item.Value.ToList());
// clear curent items
item.Value.Clear();
}
}
}
public async Task SaveProductRequests(string productId, List<QuoteDetails> productRequests)
{
// save received items to database
/// ...
}
我主要擔心的是無鎖出現以下情形:
SaveRequestsToDatabase
被解僱 - 並開始處理數據- 在撥打
item.Value.Clear();
SaveRequestsToDatabase
函數之前,外部服務會觸發另一個SaveRecentRequest
功能,其與相同的密鑰執行AddOrUpdate
- 這將增加請求到集合 SaveRequestsToDatabase
被整理並因此清除收集 - 但最初目的是通過2中添加不是集合,以便沒有處理在
你真的需要一本字典?在這段代碼中,您可以通過切換到ConcurrentQueue來輕鬆解決所有併發問題,但也許還有其他用法,您不會顯示 –
一種方法是用'ConcurrentBag'替換'List '。 –
Evk