Страница 428 из 502
<b>// Применить лямбда-выражение в качестве задачи.</b>
<b>using System;</b>
<b>using System.Threading;</b>
<b>using System.Threading.Tasks;</b>
<b>class DemoLambdaTask {</b>
<b> static void Main() {</b>
<b> Console.WriteLine("Основной поток запущен.");</b>
<b> // Далее лямбда-выражение используется для определения задачи.</b>
<b> Task tsk = Task.Factory.StartNew(() => {</b>
<b> Console.WriteLine("Задача запущена");</b>
<b> for (int count = 0; count < 10; count++) {</b>
<b> Thread.Sleep(500);</b>
<b> Console.WriteLine("Подсчет в задаче равен " + count );</b>
<b> }</b>
<b> Console.WriteLine("Задача завершена");</b>
<b> } );</b>
<b> // Ожидать завершения задачи tsk.</b>
<b> tsk.Wait();</b>
<b> // Освободить задачу tsk.</b>
<b> tsk.Dispose();</b>
<b> Console.WriteLine("Основной поток завершен.");</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы.
<b>Основной поток запущен.</b>
<b>Задача запущена</b>
<b>Подсчет в задаче равен 0</b>
<b>Подсчет в задаче равен 1</b>
<b>Подсчет в задаче равен 2</b>
<b>Подсчет в задаче равен 3</b>
<b>Подсчет в задаче равен 4</b>
<b>Подсчет в задаче равен 5</b>
<b>Подсчет в задаче равен 6</b>
<b>Подсчет в задаче равен 7</b>
<b>Подсчет в задаче равен 8</b>
<b>Подсчет в задаче равен 9</b>
<b>Задача завершена</b>
<b>Основной поток завершен.</b>
Помимо применения лямбда-выражения для описания задачи, обратите также внимание в данной программе на то, что вызов метода tsk.Dispose() не делается до тех пор, пока не произойдет возврат из метода tsk.Wait(). Как пояснялось в предыдущем разделе, метод Dispose() можно вызывать только по завершении задачи. Для того чтобы убедиться в этом, попробуйте поставить вызов метода tsk.Dispose() в рассматриваемой здесь программе перед вызовом метода tsk.Wait(). Вы сразу же заметите, что это приведет к исключительной ситуации.
Создание продолжения задачи
Одной из новаторских и очень удобных особенностей библиотеки TPL является возможность создавать продолжение задачи. Продолжение — это одна задача, которая автоматически начинается после завершения другой задачи. Создать продолжение можно, в частности, с помощью метода ContinueWith(), определенного в классе Task. Ниже приведена простейшая форма его объявления:
<b>public Task ContinueWith(Action<Task> действие_продолженмя)</b>
где действие_продолжения обозначает задачу, которая будет запущена на исполнение по завершении вызывающей задачи. У делегата Action имеется единственный параметр типа Task. Следовательно, вариант делегата Action, применяемого в данном методе, выглядит следующим образом.
<b>public delegate void Action<in T>(T obj) </b>
В данном случае обобщенный параметр Т обозначает класс Task.
Продолжение задачи демонстрируется на примере следующей программы.
<b>// Продемонстрировать продолжение задачи. </b>
<b>using System; </b>
<b>using System.Threading; </b>
<b>using System.Threading.Tasks; </b>
<b>class ContinuationDemo { </b>
<b> // Метод, исполняемый как задача,</b>
<b> static void MyTask() { </b>
<b> Console.WriteLine("MyTask() запущен"); </b>
<b> for(int count = 0; count < 5; count++) { </b>
<b> Thread.Sleep(500); </b>
<b> Console.WriteLine("В методе MyTask() подсчет равен " + count ); </b>
<b> }</b>
<b> Console.WriteLine("MyTask завершен"); </b>
<b> }</b>
<b> // Метод, исполняемый как продолжение задачи,</b>
<b> static void ContTask(Task t) { </b>
<b> Console.WriteLine("Продолжение запущено"); </b>