【问题标题】:C# Dictionary Index was outside the bounds of the array with lockC# 字典索引超出了带锁的数组的范围
【发布时间】: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


【解决方案1】:

dict.Remove(someKey); 不在锁内运行。它在不同的线程上运行。此代码未正确同步。

您可能需要的是lock (dick) dict.Remove(someKey);。然后,字典将正确运行。但是,AddRemove 不会是一个原子操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多