收集被修改;不能执行枚举操作.锁在任何可能的地方都被使用
本文关键字:任何可 修改 不能 执行 操作 枚举 | 更新日期: 2023-09-27 18:15:30
这是一个只有我自己编写和使用的小程序。
现在我要编写所有区域的代码,我使用了导致这个问题的哈希集
我不明白这怎么可能。此项仅在主窗口
中使用。hsProxyList是一个哈希集
HashSet<string> hsProxyList = new HashSet<string>();
错误发生在下面的迭代
lock (hsProxyList)
{
int irRandomProxyNumber = GenerateRandomValue.GenerateRandomValueMin(hsProxyList.Count, 0);
int irLocalCounter = 0;
foreach (var vrProxy in hsProxyList)
{
if (irLocalCounter == irRandomProxyNumber)
{
srSelectedProxy = vrProxy;
break;
}
irLocalCounter++;
}
}
}
我使用hsProxyList的其他地方
我没有锁定对象,当我得到它的计数-我想这不会导致任何错误,但可能不正确-不是致命的重要
lblProxyCount.Content = "remaining proxy count: " + hsProxyList.Count;
新lock (hsProxyList)
{
hsProxyList.Remove(srSelectedProxy);
}
新lock (hsProxyList)
{
hsProxyList = new HashSet<string>();
foreach (var vrLine in File.ReadLines(cmbBoxSelectProxy.SelectedItem.ToString()))
{
hsProxyList.Add(vrLine);
}
}
可以看出我到处都在使用锁。这是一个多线程软件。所有hsProxyList都在mainwindow . example .cs中使用-它是一个c# WPF应用程序
问题出在
lock (hsProxyList)
{
hsProxyList = new HashSet<string>();
// etc
}
所有的锁都在一个特定的对象上,但是当你做hsProxyList = new HashSet<string>();
时,你改变了对象,所以变量hsProxyList所引用的对象不再被锁定。
这里有两个问题。第一个,已经指出的是,你锁定了哈希集,同时也改变了对象hsProxyList
指向:
lock (hsProxyList)
{
hsProxyList = new HashSet<string>();
// hsProxyList is no longer locked.
}
第二个(也是更微妙的)问题是,您假设Count
不需要锁。这不是一个安全的假设。首先,你不知道HashSet
是怎么实现的。Count是O(1)
操作这一事实表明存在一个成员变量来跟踪计数。这意味着在Add
或Remove
上必须更新该变量。Add
的实现可能看起来像这样:
bool Add( T item ) {
this.count++;
// Point A.
addItemToHashSet(item);
}
注意,count
变量是递增的,然后添加项。如果调用Add
的线程在点A处中断,并且执行了另一个调用Count
的线程,您将收到一个高于实际元素数量的计数(count
增加了,但addItemToHashSet
没有增加)。
这可能不会产生任何严重的后果,但是如果在Count
元素上迭代,则可能导致崩溃。在调用Remove
时也可能出现类似的行为。