Получить список объектов из коллекции, обновляемой потоком - PullRequest
0 голосов
/ 12 января 2011

У меня есть словарь элементов, которые обновляет тема. Я хочу, чтобы метод получил обновленный список элементов, используя другой поток.

Вроде так:

    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 ]

2 голосов
/ 12 января 2011

Измените Dictionary на ConcurrentDictionary, если вы используете .NET 4. Вот простой пример, чтобы смоделировать ваш вопрос и решить его.

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 голосов
/ 12 января 2011

Там не будет гарантированный потокобезопасный способ доступа к словарю.Лучше всего либо изменить код, чтобы не делить коллекцию, либо заблокировать словарь при доступе:

object dictLock = new object();

internal List<string> GetListOfEntities()
{            
    lock (dictLock)
    {
        return ModelFacade._totalListOfStkObjects.Keys.ToList();
    }
}

Убедитесь, что вы также заблокировали словарь при изменении его в другом потоке.

0 голосов
/ 12 января 2011

Вы можете заключить словарь в однозадачный класс, ориентированный на многопотоковое исполнение. Это должно обеспечить всю функциональность ConcurrentDictionary to 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;
        }
    }
}

Смотрите здесь для получения дополнительной информации о шаблоне Singleton в C #. Обратите внимание, что существует только одно различие между шаблоном по этой ссылке и моим примером кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...