Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
13
Добавлен:
03.11.2018
Размер:
614.46 Кб
Скачать

Коллекции, поддерживающие параллелизм

Библиотека параллельных расширений содержит набор классов, представляющих коллекции с различным уровнем поддержки параллелизма. Указанные классы сосредоточены в пространстве имён System.Collections.Concurrent.

Класс BlockingCollection<T> является реализацией шаблона «поставщик-потребитель»1. Этот класс реализует интерфейсы IEnumerable<T>, ICollection, IDisposable, и имеет собственные элементы, описанные в табл. 21.

Таблица 21

Элементы класса BlockingCollection<T>

Имя элемента

Описание

Add()

Добавляет элемент в коллекцию

AddToAny()

Статический метод, который добавляет элемент в любую из указанных BlockingCollection<T>

CompleteAdding()

После вызова этого метода добавление элементов невозможно

GetConsumingEnumerable()

Возвращает перечислитель, который перебирает элементы с их одновременным удалением из коллекции

Take()

Получает элемент и удаляет его из коллекции. Если коллекция пуста, и у коллекции был вызван метод CompleteAdding(), генерируется исключение

TakeFromAny()

Статический метод, который получает элемент из любой указанной BlockingCollection<T>

TryAdd()

Пытается добавить элемент в коллекцию, в случае успеха возвращает true. Дополнительно может быть задан временной интервал и токен отмены

TryAddToAny()

Статический метод, который пытается добавить элемент в любую из указанных коллекций

TryTake()

Пытается получить элемент (с удалением из коллекции), в случае успеха возвращает true

TryTakeFromAny()

Статический метод, который пытается получить элемент из любой указанной BlockingCollection<T>

BoundedCapacity

Свойство возвращает максимальное число элементов, которое можно добавить в коллекцию без блокировки поставщика (данный параметр может быть указан при вызове конструктора BlockingCollection<T>)

IsAddingCompleted

Возвращает true, если вызывался CompleteAdding()

IsCompleted

Возвращает true, если вызывался CompleteAdding() и коллекция пуста

Продемонстрируем работу с BlockingCollection<T>, используя десять задач в качестве поставщика и одну в качестве потребителя:

BlockingCollection<int> bc = new BlockingCollection<int>();

for (int producer = 0; producer < 10; producer++)

{

Task.Factory.StartNew(() =>

{

Random rand = new Random();

for (int i = 0; i < 5; i++)

{

Thread.Sleep(200);

bc.Add(rand.Next(100));

}

});

}

var consumer = Task.Factory.StartNew(() =>

{

foreach (var item in bc.GetConsumingEnumerable())

{

Console.WriteLine(item);

}

});

consumer.Wait();

Классы ConcurrentQueue<T>, ConcurrentStack<T>, ConcurrentBag<T> и ConcurrentDictionary<T> ‑ это потокобезопасные классы для представления очереди, стека, неупорядоченного набора объектов и словаря. Предполагается, что данные классы будут использоваться в качестве разделяемых между потоками ресурсов вместо обычных классов-коллекций. Отличительная особенность данных коллекций – наличие Try-методов для получения (изменения) элементов. Такие методы удобны, так как исключают предварительные проверки существования и необходимость использования в клиентском коде секции lock.

// обычный стек Stack<T>

T item;

if (stack.Count > 0) // проверяем наличие элементов

{

item = stack.Pop(); // затем извлекаем элемент

UseData(item);

}

// стек ConcurrentStack<T>

T item;

if (concurrentStack.TryPop(out item)) // пытаемся извлечь элемент

{

UseData(item);

}