|
Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Томский политехнический университет
Опубликован: 23.01.2013 | Доступ: свободный | Студентов: 1163 / 197 | Длительность: 12:09:00
Тема: Программирование
Специальности: Программист, Архитектор программного обеспечения
Лекция 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
