Читать «C# 4.0: полное руководство» онлайн - страница 633
Герберт Шилдт
Для работы с коллекцией типа BlockingCollection<T>
может оказаться полезным и метод CompleteAdding()
. Ниже приведена форма его объявления.
public void CompleteAdding()
Вызов этого метода означает, что в коллекцию не будет больше добавлено ни одного элемента. Это приводит к тому, что свойство IsAddingComplete
принимает логическое значение true
. Если же коллекция пуста, то свойство IsCompleted
принимает логическое значение true
, и в этом случае вызовы метода Таке()
не блокируются. Ниже приведены формы объявления свойств IsAddingComplete
и IsCompleted
.
public bool IsCompleted { get; }
public bool IsAddingComplete { get; }
Когда коллекция типа BlockingCollection<T>
только начинает формироваться, эти свойства содержат логическое значение false
. А после вызова метода CompleteAdding()
они принимают логическое значение true
.
Ниже приведен вариант предыдущего примера программы, измененный с целью продемонстрировать применение метода CompleteAdding()
, свойства IsCompleted
и метода TryTake()
.
// Применение методов CompleteAdding(), TryTake()
// и свойства IsCompleted.
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);
}
bc.CompleteAdding();
}
// Потреблять символы до тех пор, пока их будет производить поставщик.
static void Consumer() {
char ch;
while(!bc.IsCompleted) {
if(bc.TryTake(out ch))
Console.WriteLine("Потребляется символ " + ch);
}
}
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();
}
}
}
Этот вариант программы дает такой же результат, как и предыдущий. Главное его отличие заключается в том, что теперь метод Producer()
может производить и поставлять сколько угодно элементов. С этой целью он просто вызывает метод CompleteAdding()
, когда завершает создание элементов. А метод Consumer()
лишь "потребляет" произведенные элементы до тех пор, пока свойство IsCompleted
не примет логическое значение true
.