我有一个线程正在更新的项目词典。我希望有一个方法使用另一个线程获取更新的项目列表。
像这样:
internal List<string> GetListOfEntities()
{
List<string> listOfEntities = new List<string>();
foreach (string entityName in ModelFacade._totalListOfStkObjects.Keys)
{
listOfEntities.Add(entityName);
}
return listOfEntities;
}
ModelFacade._totalListOfStkObjects是线程正在更新的集合。我一直得到例外:“收集被修改;枚举操作可能无法执行。”;我已经尝试将_totalListOfStkObjects复制到本地集合并在GetListOfEntities()中迭代它..但是我得到了同样的错误..?
任何帮助?
WulfgarPro
答案 0 :(得分:2)
无法保证以线程安全的方式访问字典。您最好的办法是更改代码,以便在访问时不共享集合或锁定字典:
object dictLock = new object();
internal List<string> GetListOfEntities()
{
lock (dictLock)
{
return ModelFacade._totalListOfStkObjects.Keys.ToList();
}
}
确保在另一个线程中修改字典时也锁定字典。
答案 1 :(得分:2)
如果您使用的是.NET,请将Dictionary
更改为ConcurrentDictionary
。以下是模拟问题并解决问题的简单示例。
class DataItem
{
public int Data { get; set; }
public bool IsDirty { get; set; }
}
var data = new ConcurrentDictionary<string, DataItem>();
Thread addingItems = new Thread(() =>
{
for (int i = 0; i < 10000; i++)
{
data.TryAdd("data " + i, new DataItem { Data = i, IsDirty = true });
Thread.Sleep(100);
}
});
Thread fetchingItems = new Thread(() =>
{
int count = 0;
while (count < 100)
{
foreach (var item in data)
{
if (item.Value.IsDirty)
{
Console.WriteLine(item.Key + " " + item.Value);
item.Value.IsDirty = false;
count++;
}
}
}
});
addingItems.Start();
fetchingItems.Start();
答案 2 :(得分:0)
您可以将字典包装在线程安全的单例类中。这应该提供ConcurrentDictionary到Dictionary的所有功能。引用字典只需要一个额外的间接层。
参考:
Singleton.Instance.myDictionary.Add(1, "Hello World");
声明:
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
public Dictionary<int, string> myDictionary = new Dictionary<int, string>();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
查看here以获取有关C#中Singleton模式的更多信息。请注意,此链接上的模式与我的示例代码之间只有一个区别。