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

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

<b>    Console.WriteLine(&quot;Основной поток запущен.&quot;);</b>

<b>    // Выполнить параллельно два именованных метода.</b>

<b>    Parallel.Invoke(MyMeth, MyMeth2);</b>

<b>    Console.WriteLine(&quot;Основной поток завершен.&quot;);</b>

<b>  }</b>

<b>}</b>

Выполнение этой программы может привести к следующему результату.

<b>Основной поток запущен.</b>

<b>MyMeth запущен</b>

<b>MyMeth2 запущен</b>

<b>В методе MyMeth подсчет равен 0</b>

<b>В методе MyMeth2, подсчет равен 0</b>

<b>В методе MyMeth подсчет равен 1</b>

<b>В методе MyMeth2, подсчет равен 1</b>

<b>В методе MyMeth подсчет равен 2</b>

<b>В методе MyMeth2, подсчет равен 2</b>

<b>В методе MyMeth подсчет равен 3</b>

<b>В методе MyMeth2, подсчет равен 3</b>

<b>В методе MyMeth подсчет равен 4</b>

<b>MyMeth завершен</b>

<b>В методе MyMeth2, подсчет равен 4</b>

<b>MyMeth2 завершен</b>

<b>Основной поток завершен.</b>

В данном примере особое внимание обращает на себя следующее обстоятельство: выполнение метода Main() приостанавливается до тех пор, пока не произойдет возврат из метода Invoke(). Следовательно, метод Main(), в отличие от методов MyMeth() и MyMeth2(), не выполняется параллельно. Поэтому применять метод Invoke() показанным здесь способом нельзя в том случае, если требуется, чтобы исполнение вызывающего потока продолжалось.

В приведенном выше примере использовались именованные методы, но для вызова метода Invoke() это условие не является обязательным. Ниже приведен переделанный вариант той же самой программы, где в качестве аргументов в вызове метода Invoke() применяются лямбда-выражения.

<b>// Применить метод Parallel.Invoke() </b>

<b>//для параллельного выполнения двух методов. </b>

<b>// В этой версии программы применяются лямбда-выражения. </b>

<b>using System; </b>

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

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

<b>class DemoParallel { </b>

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

<b>    Console.WriteLine(&quot;Основной поток запущен.&quot;); </b>

<b>    // Выполнить два анонимных метода, указываемых в лямбда-выражениях. </b>

<b>    Parallel.Invoke(() =&gt; { </b>

<b>      Console.WriteLine(&quot;Выражение #1 запущено&quot;); </b>

<b>      for(int count = 0; count &lt; 5; count++) { </b>

<b>        Thread.Sleep(500); </b>

<b>        Console.WriteLine(&quot;В выражении #1 подсчет равен &quot; + count ); </b>

<b>      } </b>

<b>      Console.WriteLine(&quot;Выражение #1 завершено&quot;); </b>

<b>    }, </b>

<b>    () =&gt; { </b>

<b>      Console.WriteLine(&quot;Выражение #2 запущено&quot;); </b>

<b>      for (int count = 0; count &lt; 5; count++) { </b>

<b>        Thread.Sleep(500); </b>

<b>        Console.WriteLine(&quot;В выражении #2 подсчет равен &quot; + count ); </b>

<b>      } </b>

<b>      Console.WriteLine(&quot;Выражение #1 завершено&quot;); </b>

<b>    } );</b>

<b>    Console.WriteLine(&quot;Основной поток завершен.&quot;); </b>

<b>  } </b>

<b>} </b>

Эта программа дает результат, похожий на результат выполнения предыдущей программы.

В TPL параллелизм данных поддерживается, в частности, с помощью метода For(), определенного в классе Parallel. Этот метод существует в нескольких формах. Его рассмотрение мы начнем с самой простой формы, приведенной ниже:

<b>public static ParallelLoopResult</b>

<b>                For(int fromlnclusive, int toExclusive, Action&lt;int&gt; body)</b>

где fromlnclusive обозначает начальное значение того, что соответствует переменной управления циклом; оно называется также итерационным, или индексным, значением; a toExclusive — значение, на единицу больше конечного. На каждом шаге цикла переменная управления циклом увеличивается на единицу. Следовательно, цикл постепенно продвигается от начального значения fromlnclusive к конечному значению toExclusive минус единица. Циклически выполняемый код указывается методом, передаваемым через параметр body. Этот метод должен быть совместим с делегатом Action&lt;int&gt;, объявляемым следующим образом.