Как видите, в нескольких классах параллельных коллекций реализуется интерфейс IProducerConsumerCollection
. Этот интерфейс также определен в пространстве имен System.Collections.Concurrent
. Он служит в качестве расширения интерфейсов IEnumerable, IEnumerable
и ICollection
. Кроме того, в нем определены методы TryAdd()
и TryTake()
, поддерживающие шаблон "поставщик-потребитель". (Классический шаблон "поставщик-потребитель" отличается решением двух задач. Первая задача производит элементы коллекции, а другая потребляет их.) Метод TryAdd()
пытается добавить элемент в коллекцию, а метод TryTake()
— удалить элемент из коллекции. Ниже приведены формы объявления обоих методов.
bool TryAdd(Т item)
bool TryTake(out T item)
Метод TryAdd()
возвращает логическое значение true
, если в коллекцию добавлен элемент TryTake()
возвращает логическое значение true
, если элемент iTryAdd()
выполнен успешно, то элемент iIProducerConsumerCollection
указывается перегружаемый вариант метода CopyTo()
, определяемого в интерфейсе ICollection
, а также метода ТоАггау()
, копирующего коллекцию в массив.)
Параллельные коллекции зачастую применяются в комбинации с библиотекой распараллеливания задач (TPL) или языком PLINQ. В силу особого характера этих коллекций все их классы не будут рассматриваться далее подробно. Вместо этого на конкретных примерах будет дан краткий обзор класса BlockingCollection
. Усвоив основы построения класса BlockingCollection
, вы сможете без особого труда разобраться и в остальных классах параллельных коллекций.
В классе BlockingCollection
, по существу, реализуется блокирующая очередь. Это означает, что в такой очереди автоматически устанавливается ожидание любых попыток вставить элемент в коллекцию, когда она заполнена, а также попыток удалить элемент из коллекции, когда она пуста. Это идеальное решение для тех ситуаций, которые связаны с применением шаблона "поставщик-потребитель". В классе BlockingCollection
реализуются интерфейсы ICollection, IEnumerable, IEnumerable
, а также IDisposable
.
В классе BlockingCollection
определяются следующие конструкторы.
public BlockingCollection()
public BlockingCollection(int boundedCapacity)
public BlockingCollection(IProducerConsumerCollection
public BlockingCollection(IProducerConsumerCollection
int boundedCapacity)
В двух первых конструкторах в оболочку класса BlockingCollection
заключается коллекция, являющаяся экземпляром объекта типа ConcurrentQueue
. А в двух других конструкторах можно указать коллекцию, которая должна быть положена в основу коллекции типа BlockingCollection
. Если указывается параметр
Помимо методов TryAdd()
и TryTake()
, определяемых параллельно с теми, что указываются в интерфейсе IProducerConsumerCollection
, в классе BlockingCollection
определяется также ряд собственных методов. Ниже представлены методы, которые будут использоваться в приведенных далее примерах.
public void Add(T item)
public T Take()
Когда метод Add()
вызывается для неограниченной коллекции, он добавляет элемент Add()
вызывается для ограниченной коллекции, он блокирует доступ к ней, если она заполнена. После того как из коллекции будет удален один элемент или больше, указанный элемент Таке()
удаляет элемент из коллекции и возвращает управление вызывающей части программы. (Имеются также варианты обоих методов, принимающие в качестве параметра признак задачи как экземпляр объекта типа CancellationToken
.)