Добавить в цитаты Настройки чтения

Страница 473 из 502

<b>    for(char ch = 'A'; ch &lt;= 'Z'; ch++) {</b>

<b>      bc.Add(ch);</b>

<b>      Console.WriteLine (&quot;Производится символ &quot; + ch) ;</b>

<b>    }</b>

<b>  }</b>

<b>  // Потребить 26 символов,</b>

<b>  static void Consumer() {</b>

<b>    for(int i=0; i &lt; 26; i++)</b>

<b>    Console .WriteLine (&quot;Потребляется символ &quot; + bc.Take());</b>

<b>  }</b>

<b>  static void Main() {</b>

<b>    // Использовать блокирующую коллекцию, ограниченную 4 элементами,</b>

<b>    bc = new BlockingCollection&lt;char&gt;(4);</b>

<b>    // Создать задачи поставщика и потребителя.</b>

<b>    Task Prod = new Task(Producer);</b>

<b>    Task Con = new Task(Consumer);</b>

<b>    // Запустить задачи.</b>

<b>    Con.Start();</b>

<b>    Prod.Start();</b>

<b>    // Ожидать завершения обеих задач,</b>

<b>    try {</b>

<b>      Task.WaitAll(Con, Prod);</b>

<b>    } catch(AggregateException exc) {</b>

<b>      Console.WriteLine (exc);</b>

<b>    } finally {</b>

<b>      Con.Dispose();</b>

<b>      Prod.Dispose();</b>

<b>      bc.Dispose();</b>

<b>    }</b>

<b>  }</b>

<b>}</b>

Если запустить эту программу на выполнение, то на экране появится смешанный результат, выводимый поставщиком и потребителем. Отчасти это объясняется тем, что коллекция bс ограничена 4 элементами, а это означает, что в нее может быть добавлено только четыре элемента, прежде чем ее придется сократить. В качестве эксперимента попробуйте сделать коллекцию bс неограниченной и понаблюдайте за полученными результатами. В некоторых средах выполнения это приведет к тому, что все элементы коллекции будут сформированы до того, как начнется какое-либо их потребление. Кроме того, попробуйте ограничить коллекцию одним элементом. В этом случае одновременно может быть сформирован лишь один элемент.

Для работы с коллекцией типа BlockingCollection&lt;T&gt; может оказаться полезным и метод CompleteAdding(). Ниже приведена форма его объявления.

<b>public void CompleteAdding()</b>

Вызов этого метода означает, что в коллекцию не будет больше добавлено ни одного элемента. Это приводит к тому, что свойство IsAddingComplete принимает логическое значение true. Если же коллекция пуста, то свойство IsCompleted принимает логическое значение true, и в этом случае вызовы метода Таке() не блокируются. Ниже приведены формы объявления свойств IsAddingComplete и IsCompleted.

<b>public bool IsCompleted { get; }</b>

<b>public bool IsAddingComplete { get; }</b>

Когда коллекция типа BlockingCollection&lt;T&gt; только начинает формироваться, эти свойства содержат логическое значение false. А после вызова метода CompleteAdding() они принимают логическое значение true.

Ниже приведен вариант предыдущего примера программы, измененный с целью продемонстрировать применение метода CompleteAdding(), свойства IsCompleted и метода TryTake().

<b>// Применение методов CompleteAdding(), TryTake()</b>

<b>// и свойства IsCompleted.</b>

<b>using System;</b>

<b>using System.Threading.Tasks;</b>

<b>using System.Threading;</b>

<b>using System.Collections.Concurrent;</b>

<b>class BlockingDemo {</b>

<b>  static BlockingCollection&lt;char&gt; bc;</b>

<b>  // Произвести и поставить символы от А до Z.</b>

<b>  static void Producer() {</b>

<b>    for (char ch = 'A'; ch &lt;= 'Z'; ch++) {</b>

<b>      bc.Add(ch);</b>

<b>      Console.WriteLine(&quot;Производится символ &quot; + ch);</b>

<b>    }</b>

<b>    bc.CompleteAdding();</b>

<b>  }</b>

<b>  // Потреблять символы до тех пор, пока их будет производить поставщик.</b>

<b>  static void Consumer() {</b>

<b>    char ch;</b>

<b>    while(!bc.IsCompleted) {</b>

<b>      if(bc.TryTake(out ch))</b>