Читать «C# 4.0: полное руководство» онлайн - страница 632
Герберт Шилдт
Помимо методов TryAdd()
и TryTake()
, определяемых параллельно с теми, что указываются в интерфейсе IProducerConsumerCollection<T>
, в классе BlockingCollection<T>
определяется также ряд собственных методов. Ниже представлены методы, которые будут использоваться в приведенных далее примерах.
public void Add(T item)
public T Take()
Когда метод Add()
вызывается для неограниченной коллекции, он добавляет элемент Add()
вызывается для ограниченной коллекции, он блокирует доступ к ней, если она заполнена. После того как из коллекции будет удален один элемент или больше, указанный элемент Таке()
удаляет элемент из коллекции и возвращает управление вызывающей части программы. (Имеются также варианты обоих методов, принимающие в качестве параметра признак задачи как экземпляр объекта типа CancellationToken
.)
Применяя методы Add()
и Таке()
, можно реализовать простой шаблон "поставщик-потребитель", как показано в приведенном ниже примере программы. В этой программе создается поставщик, формирующий символы от А до Z, а также потребитель, получающий эти символы. При этом создается коллекция типа BlockingCollection<T>
, ограниченная 4 элементами.
// Простой пример коллекции типа BlockingCollection.
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;
class BlockingDemo {
static BlockingCollection<char> bc;
// Произвести и поставить символы от А до Z.
static void Producer() {
for(char ch = 'A'; ch <= 'Z'; ch++) {
bc.Add(ch);
Console.WriteLine ("Производится символ " + ch) ;
}
}
// Потребить 26 символов,
static void Consumer() {
for(int i=0; i < 26; i++)
Console .WriteLine ("Потребляется символ " + bc.Take());
}
static void Main() {
// Использовать блокирующую коллекцию, ограниченную 4 элементами,
bc = new BlockingCollection<char>(4);
// Создать задачи поставщика и потребителя.
Task Prod = new Task(Producer);
Task Con = new Task(Consumer);
// Запустить задачи.
Con.Start();
Prod.Start();
// Ожидать завершения обеих задач,
try {
Task.WaitAll(Con, Prod);
} catch(AggregateException exc) {
Console.WriteLine (exc);
} finally {
Con.Dispose();
Prod.Dispose();
bc.Dispose();
}
}
}
Если запустить эту программу на выполнение, то на экране появится смешанный результат, выводимый поставщиком и потребителем. Отчасти это объясняется тем, что коллекция bс ограничена 4 элементами, а это означает, что в нее может быть добавлено только четыре элемента, прежде чем ее придется сократить. В качестве эксперимента попробуйте сделать коллекцию bс неограниченной и понаблюдайте за полученными результатами. В некоторых средах выполнения это приведет к тому, что все элементы коллекции будут сформированы до того, как начнется какое-либо их потребление. Кроме того, попробуйте ограничить коллекцию одним элементом. В этом случае одновременно может быть сформирован лишь один элемент.