Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Опубликован: 23.01.2013 | Уровень: для всех | Доступ: платный | ВУЗ: Томский политехнический университет
Лекция 11:
Параллельные коллекции. Низкоуровневая синхронизация
ConcurrentDictionary
Коллекция ConcurrentDictionary представляет собой потокобезопасную коллекцию пар "ключ-значение", доступ к которой могут одновременно получать несколько потоков. Для доступа к элементам коллекции в не блокирующем режиме служат методы TryAdd(), TryGetValue(), TryRemove() и TryUpdate() (Табл. 15.6). Поскольку элементы основаны на ключах и значениях, ConcurrentDictionary<TKey, TVal> не реализует интерфейс IProducerConsumerCollection<T>.
Имя | Описание |
---|---|
TryAdd(TKey, TVal) | Пытается добавить указанную пару "ключ-значение" в коллекцию. |
TryGetValue(TKey, out TVal) | Пытается получить значение, связанное с указанным ключом, из коллекции. |
TryRemove(TKey, out TVal) | Пытается удалить и вернуть значение с указанным ключом из коллекции. |
TryUpdate(TKey, TVal, TVal) | Сравнивает существующее значение указанного ключа с заданным значением и в случае их равенства обновляет ключ третьим значением. |
ContainsKey(TKey) | Определяет, содержится ли указанный ключ в словаре |
GetOrAdd (TKey, TVal) | Добавляет пару "ключ значение" в коллекцию, если ключ еще не существует. |
AddOrUpdate (TKey, TVal, Func<TKey, TVal, TVal>) | Добавляет пару "ключ значение" в коллекцию, если данный ключ еще не существует, или обновляет пару "ключ. |
Методы, представленные в Табл. 15.6, следует использовать в следующих случаях:
- Метод AddOrUpdate() используют, если необходимо добавить новое значение для заданного ключа, а также в том случае если ключ уже существует и необходимо заменить его значение;
- Метод GetOrAdd() используют, если необходимо получить существующее значение для заданного ключа, а также в том случае если ключ не существует и задать значение паре "ключ-значение";
- Методы TryAdd(), TryGetValue(), TryUpdate(), TryRemove() используют, если необходимо добавить, получить, обновить или удалить пару "ключ-значение", а также в том случае, если ключ уже существует или попытка завершилась по какой-либо причине ошибкой и необходимо выполнить альтернативные действия.
Пример использования коллекции ConcurrentDictionary представлен ниже:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.Concurrent; using System.Threading.Tasks; namespace ConcurrentDictionaryExample { class BankAccount { public int Balance { get; set; } class Program { static void Main(string[] args) { // создаем экземпляр банковского счета BankAccount account = new BankAccount(); // создаем коллекцию ConcurrentDictionary<object, int> sharedDict = new ConcurrentDictionary<object, int>(); // создаем список задач, которые возвращают целочисленный массив Task<int>[] tasks = new Task<int>[10]; for (int i = 0; i < tasks.Length; i++) { // помещаем начальные значения в словарь sharedDict.TryAdd(i, account.Balance); // создаем новую задачу tasks[i] = new Task<int>((keyObj) => { // создаем переменную для использования в цикле int currentValue; bool gotValue; // создаем цикл для обновления баланса счета for (int j = 0; j < 1000; j++) { // получаем текущее значение из словаря gotValue = sharedDict.TryGetValue(keyObj, out currentValue); // увеличиваем значение и обновляем словарь sharedDict.TryUpdate(keyObj, currentValue + 1, currentValue); } // создаем переменную конечного результата int result; // получаем результат из словаря gotValue = sharedDict.TryGetValue(keyObj, out result); // возвращаем значение результата, если есть if (gotValue) { return result; } else { // если нет результата - вызываем исключение throw new Exception( String.Format("Нет элементов данных доступных для объекта {0}", keyObj)); } }, i); // запускаем задачу tasks[i].Start(); } // обновляем баланс счета с помощью результатов выполнения задач for (int i = 0; i < tasks.Length; i++) { account.Balance += tasks[i].Result; } // выводим значение счетчика Console.WriteLine("Ожидаемое значение: {0}, Баланс: {1}", 10000, account.Balance); Console.ReadLine(); } } } }
увеличить изображение
Рис. 15.6. Результат выполнения программы использующую коллекцию ConcurrentDictionary