从线程更新的集合中获取对象列表

时间:2011-01-12 03:36:43

标签: c# collections

我有一个线程正在更新的项目词典。我希望有一个方法使用另一个线程获取更新的项目列表。

像这样:

    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

3 个答案:

答案 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模式的更多信息。请注意,此链接上的模式与我的示例代码之间只有一个区别。