gpt4 book ai didi

c# - 在字典中的对象上使用锁会产生 KeyNotFoundException

转载 作者:太空狗 更新时间:2023-10-29 21:44:49 25 4
gpt4 key购买 nike

我有一些处理大量 response 的代码并行地从我的数据库中获取对象(使用 AsParallel() )。每个response有很多components . responses可能共享相同的组件。我对 component 做了一些修改数据并将其保存到数据库中,因此我需要防止多个线程处理同一个 component同时反对。

我使用锁来实现这一点。我有一个 ConcurrentDictionary<int, object>持有所有必要的锁对象。像这样:

private static ConcurrentDictionary<int, object> compLocks = new ConcurrentDictionary<int, object>(); 
var compIds = db.components.Select(c => c.component_id).ToList();
foreach (var compId in compIds)
{
compLocks[compId] = new object();
}

然后我会这样做:

responses.AsParallel().ForAll(r =>
{

... do some time consuming stuff with web services ...

// this is a *just in case* addition,
// in case a new component was added to
// the db since the dictionary was constructed
// NOTE: it did not have any effect, and I'm no longer
// using it as @Henk pointed out it is not thread-safe.
//if (compLocks[c.component_id] == null)
//{
// compLocks[c.component_id] = new object();
//}

componentList.AsParallel().ForAll(c =>
{
lock (compLocks[c.component_id])
{
... do some processing, save the db records ...
}
});
});

这似乎运行得很好,但在程序执行结束时(它运行了几个小时,因为有很多数据)我得到以下异常:

Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)

我确定 ConcurrentDictionary正在填充所有可能的 component身份证。

我有 3 个问题:

  1. 这种异常怎么可能发生,我该如何解决?
  2. 我需要 ConcurrentDictionary 吗?为此?
  3. 在这种情况下,我对锁定工作原理的理解是否正确/是否有更好的方法?

回答后编辑

要弄清楚这一切的原因是什么,那就是 .AsParallel()没有枚举 responses 的集合.它是惰性评估的,意思是新的 responses (因此新的 components )可以在运行时(从其他进程)添加到集合中。使用 .ToList() 强制执行快照在 .AsParallel() 之前解决了问题。

我添加的代码component ID 为 compLocks在运行时没有解决这个问题是因为它不是线程安全的。

最佳答案

1) How is this exception even possible?

显然是的,但不是仅从发布的代码来看。如果将数据添加到数据库中,就会发生这种情况(是否可以选择预先使用 ToList() 捕获 responses?)

2) Do I need a ConcurrentDictionary for this?

不是固定列表,但是当解决方案涉及缺失时添加,那么是的,您需要一个并发集合。

3) Is my understanding of how locking works correct in this instance / is there a better way of doing this?

不太确定。锁定看起来没问题,但您仍然会多次处理重复项。只是不同时。


对编辑的 react :

if (compLocks[c.component_id] == null)
{
compLocks[c.component_id] = new object();
}

这不是线程安全的。现在可以为 1 个 component_id 值创建多个锁对象。您需要使用其中一种 GetOrAdd() 方法。

但我不希望这会导致您遇到异常,因此这可能不是直接问题。

关于c# - 在字典中的对象上使用锁会产生 KeyNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21185206/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com