避免concurrentdictionary抛出addduplicatekeyexception的核心方法是不使用add方法,而应使用tryadd、addorupdate或getoradd等原子性操作。1. 使用tryadd(key, value):当键不存在时添加,存在则返回false,不抛异常;2. 使用addorupdate(key, addvalue, updatevaluefactory):键不存在时添加,存在时按委托更新;3. 使用getoradd(key, valuefactory):获取键值,不存在时通过工厂方法添加;4. 避免containskey后调用add的模式,因其存在竞态条件;5. 根据业务逻辑选择tryadd(键存在时忽略)或addorupdate(键存在时更新);6. 注意并发下迭代的弱一致性、热点键竞争及值对象的线程安全问题,始终优先使用原子方法确保操作安全。

避免
ConcurrentDictionary
AddDuplicateKeyException
Add
TryAdd
AddOrUpdate
GetOrAdd
要彻底避免
AddDuplicateKeyException
ConcurrentDictionary
Dictionary
最直接的解决方案是:
使用 TryAdd(TKey key, TValue value)
ConcurrentDictionary<string, int> myConcurrentDict = new ConcurrentDictionary<string, int>();
if (myConcurrentDict.TryAdd("item1", 100))
{
Console.WriteLine("成功添加 item1。");
}
else
{
Console.WriteLine("item1 已存在,未添加。");
}
// 再次尝试添加,会返回 false
if (!myConcurrentDict.TryAdd("item1", 200))
{
Console.WriteLine("再次尝试添加 item1 失败,因为它已经存在。");
}使用 AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
ConcurrentDictionary<string, int> userScores = new ConcurrentDictionary<string, int>();
// 用户第一次得分
userScores.AddOrUpdate("Alice", 100, (key, existingValue) => existingValue + 0); // 这里的 updateValueFactory 不会被调用
Console.WriteLine($"Alice 的得分: {userScores["Alice"]}"); // 输出 100
// 用户再次得分,累加
userScores.AddOrUpdate("Alice", 50, (key, existingValue) => existingValue + 50);
Console.WriteLine($"Alice 更新后的得分: {userScores["Alice"]}"); // 输出 150使用 GetOrAdd(TKey key, TValue value)
GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
ConcurrentDictionary<string, string> cache = new ConcurrentDictionary<string, string>();
// 第一次获取,键不存在,会添加并返回 "DataForA"
string dataA = cache.GetOrAdd("KeyA", "DataForA");
Console.WriteLine($"获取或添加 KeyA: {dataA}");
// 第二次获取,键已存在,直接返回 "DataForA",不会调用工厂方法或重新添加
string dataA_again = cache.GetOrAdd("KeyA", "NewDataForA"); // 这个 "NewDataForA" 不会被用到
Console.WriteLine($"再次获取 KeyA: {dataA_again}");避免使用
ContainsKey
Add
Add
ContainsKey
AddDuplicateKeyException
ConcurrentDictionary
ConcurrentDictionary
AddDuplicateKeyException
这其实是一个非常常见的问题,很多人在从普通
Dictionary
ConcurrentDictionary
ConcurrentDictionary
Add
Add
ConcurrentDictionary
Add
Remove
Update
Add(key, value)
ConcurrentDictionary
Add
AddDuplicateKeyException
所以,这并不是
ConcurrentDictionary
TryAdd
AddOrUpdate
Add
TryAdd
AddOrUpdate
选择
TryAdd
AddOrUpdate
选择 TryAdd
// 缓存某个复杂计算的结果
string key = "complex_calculation_input";
if (!cache.TryAdd(key, CalculateComplexResult(key)))
{
Console.WriteLine($"Key '{key}' 已经存在,无需重复计算。");
}选择 AddOrUpdate
// 统计用户访问次数
ConcurrentDictionary<string, int> visitCounts = new ConcurrentDictionary<string, int>();
string userId = "user123";
visitCounts.AddOrUpdate(userId, 1, (key, existingCount) => existingCount + 1);
Console.WriteLine($"用户 {userId} 访问次数: {visitCounts[userId]}");总结一下,
TryAdd
AddOrUpdate
除了
AddDuplicateKeyException
ConcurrentDictionary
ConcurrentDictionary
“检查-然后-操作”的竞态条件: 前面提到过
ContainsKey
Add
if (myDict.ContainsKey(key))
{
var value = myDict[key]; // 假设这个key肯定还在
// 对value进行操作
}
else
{
// ...
}在
ContainsKey
true
myDict[key]
TryRemove
KeyNotFoundException
ConcurrentDictionary
TryGetValue
TryRemove
GetOrAdd
AddOrUpdate
迭代时的逻辑不一致:
ConcurrentDictionary
InvalidOperationException
Dictionary
myDict.ToList()
ConcurrentDictionary
性能瓶颈:过度竞争:
ConcurrentDictionary
Dictionary
ConcurrentDictionary
ConcurrentBag
ConcurrentQueue
复杂值类型的线程安全问题:
ConcurrentDictionary
TValue
ConcurrentDictionary
理解这些陷阱并选择正确的
ConcurrentDictionary
Dictionary
以上就是ConcurrentDictionary的AddDuplicateKeyException怎么避免?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号