Console.WriteLine("Основной поток запущен.");

    // Далее лямбда-выражение используется для определения задачи.

    Task tsk = Task.Factory.StartNew(() => {

      Console.WriteLine("Задача запущена");

      for (int count = 0; count < 10; count++) {

        Thread.Sleep(500);

        Console.WriteLine("Подсчет в задаче равен " + count );

      }

      Console.WriteLine("Задача завершена");

    } );

    // Ожидать завершения задачи tsk.

    tsk.Wait();

    // Освободить задачу tsk.

    tsk.Dispose();

    Console.WriteLine("Основной поток завершен.");

  }

}

Ниже приведен результат выполнения этой программы.

Основной поток запущен.

Задача запущена

Подсчет в задаче равен 0

Подсчет в задаче равен 1

Подсчет в задаче равен 2

Подсчет в задаче равен 3

Подсчет в задаче равен 4

Подсчет в задаче равен 5

Подсчет в задаче равен 6

Подсчет в задаче равен 7

Подсчет в задаче равен 8

Подсчет в задаче равен 9

Задача завершена

Основной поток завершен.

Помимо применения лямбда-выражения для описания задачи, обратите также внимание в данной программе на то, что вызов метода tsk.Dispose() не делается до тех пор, пока не произойдет возврат из метода tsk.Wait(). Как пояснялось в предыдущем разделе, метод Dispose() можно вызывать только по завершении задачи. Для того чтобы убедиться в этом, попробуйте поставить вызов метода tsk.Dispose() в рассматриваемой здесь программе перед вызовом метода tsk.Wait(). Вы сразу же заметите, что это приведет к исключительной ситуации.

<p>Создание продолжения задачи</p>

Одной из новаторских и очень удобных особенностей библиотеки TPL является возможность создавать продолжение задачи. Продолжение — это одна задача, которая автоматически начинается после завершения другой задачи. Создать продолжение можно, в частности, с помощью метода ContinueWith(), определенного в классе Task. Ниже приведена простейшая форма его объявления:

public Task ContinueWith(Action действие_продолженмя)

где действие_продолжения обозначает задачу, которая будет запущена на исполнение по завершении вызывающей задачи. У делегата Action имеется единственный параметр типа Task. Следовательно, вариант делегата Action, применяемого в данном методе, выглядит следующим образом.

public delegate void Action(T obj)

В данном случае обобщенный параметр Т обозначает класс Task.

Продолжение задачи демонстрируется на примере следующей программы.

// Продемонстрировать продолжение задачи.

using System;

using System.Threading;

using System.Threading.Tasks;

class ContinuationDemo {

  // Метод, исполняемый как задача,

  static void MyTask() {

    Console.WriteLine("MyTask() запущен");

    for(int count = 0; count < 5; count++) {

      Thread.Sleep(500);

      Console.WriteLine("В методе MyTask() подсчет равен " + count );

    }

    Console.WriteLine("MyTask завершен");

  }

  // Метод, исполняемый как продолжение задачи,

  static void ContTask(Task t) {

    Console.WriteLine("Продолжение запущено");

    for(int count = 0; count < 5; count++) {

      Thread.Sleep(500);

      Console.WriteLine("В продолжении подсчет равен " + count );

    }

    Console.WriteLine("Продолжение завершено");

  }

  static void Main() {

    Console.WriteLine("Основной поток запущен.");

    // Сконструировать объект первой задачи.

    Task tsk = new Task(MyTask);

    //А теперь создать продолжение задачи.

    Task taskCont = tsk.ContinueWith(ContTask);

Перейти на страницу:

Похожие книги