【发布时间】:2016-04-15 12:09:08
【问题描述】:
我有这个代码:
lock (dict)
{
dict.Add(someKey, someValue);
Task task = new Task (() => doSomething);
task.Start();
task.ContinueWith(() => {dict.Remove(someKey);});
}
既然我已经锁定了dict,为什么我仍然得到错误
“索引超出了数组的范围”
我无法重现该错误,但另一个人做到了。
【问题讨论】:
-
锁在你开始你的任务后立即以很好的概率被释放,读作:任务内部的代码在字典方面不是线程安全的。即使它们是同步的......锁每个线程都有效。此外,为什么您开始任务然后添加延续而不是反之亦然?最后说明:IndexOutOfRangeException 与 Dictionary 完全无关,那么它来自其他东西
-
嗨,阿德里亚诺,从堆栈跟踪来看,异常来自 dict.Add(),这就是为什么我认为它与字典有关。
-
向我们展示堆栈跟踪! Add() 可能 如果字典同时更新但从您发布的代码中它只是同步更新,则抛出它(除非您重复调用该代码块,在这种情况下是的,与 dict.Remove( ))。无论如何,解决方案是在您删除时锁定(如现在已删除的答案所示)
-
是的,foreach 循环中的代码块,我会尽快发布堆栈跟踪。
-
这就够了,它可能发生在字典更新它的桶时(在它计算桶数组的索引和访问该数组之间,如果在这两个步骤之间删除了一个元素,那么你会得到一个索引如果它是最后一个 - 或其他无效的结果)。只需:lock { dict.Remove(); }
标签: c# multithreading dictionary locking