我尝试使用BlockingCollection的值
来提供字典(...)
lock (blockingCol)
{
lock (cache)
{
cache = new Dictionary<Guid, customDocument>();
Parallel.ForEach(blockingCol,
(document) =>
{
lock (cache) //Same bug with or without this lock
cache.Add(document.Id, document);
});
blockingCol = new BlockingCollection<customDocument>();
(...)
}
(...)
}
(...)
问题是有时文档已经在cache
中。但我不明白为什么。我之前创建了一个新的cache
,BlockingCollection
不应该将同一个文档两次出列。但我认为这是Parallel
的一个问题,因为当我使用它下面的代码工作时,我需要一个多线程系统。
(...)
lock (blockingCol)
{
lock (cache)
{
cache = new Dictionary<Guid, customDocument>();
while (blockingCol.Count > 0)
{
var doc = _blockingCol.Take();
cache.Add(doc.Id, doc);
}
blockingCol = new BlockingCollection<customDocument>();
(...)
}
(...)
}
(...)
答案 0 :(得分:0)
问题既不是BlockingCollection,也不是Parallel.ForEach()调用,也不是锁定,尽管你可以通过正确使用并发数据结构来摆脱显式锁定。事实上,你使用的是普通词典&lt;&gt;在多线程代码中。
将您的代码段重写为
Parallel.ForEach(blockingCol.GetConsumingEnumerable(),
(document) =>
{
cache.AddOrUpdate(document.Id, document, (k,v) => document);
});
它将消除异常ArgumentException
,消息'字典中已存在具有相同键的元素。'
虽然这可以解决您的直接问题,但您应该完全重写该部分
cache = blockingCol.ToDictionary( d => d.Id );
Parallel.ForEach()
在性能方面不会给你带来任何好处。
另外,请检查您的制作人,确保它没有放置两个具有相同ID的文档。