Книга: C# 4.0: полное руководство

Создание продолжения задачи

Создание продолжения задачи

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

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

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

public delegate void Action<in T>(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);
    // Начать последовательность задач,
    tsk.Start();
    // Ожидать завершения продолжения.
    taskCont.Wait();
    tsk.Dispose();
    taskCont.Dispose();
    Console.WriteLine("Основной поток завершен.");
  }
}

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

Основной поток запущен.
MyTask() запущен
В методе MyTask() подсчет равен 0
В методе MyTask() подсчет равен 1
В методе MyTask() подсчет равен 2
В методе MyTask() подсчет равен 3
В методе MyTask() подсчет равен 4
MyTask завершен
Продолжение запущено
В продолжении подсчет равен 0
В продолжении подсчет равен 1
В продолжении подсчет равен 2
В продолжении подсчет равен 3
В продолжении подсчет равен 4
Продолжение завершено
Основной поток завершен.

Как следует из приведенного выше результата, вторая задача не начинается до тех пор, пока не завершится первая. Обратите также внимание на то, что в методе Main() пришлось ожидать окончания только продолжения задачи. Дело в том, что метод MyTask() как задача завершается еще до начала метода ContTask как продолжения задачи. Следовательно, ожидать завершения метода MyTask() нет никакой надобности, хотя если и организовать такое ожидание, то в этом будет ничего плохого.

Любопытно, что в качестве продолжения задачи нередко применяется лямбда-выражение. Для примера ниже приведен еще один способ организации продолжения задачи из предыдущего примера программы.

//В данном случае в качестве продолжения задачи применяется лямбда-выражение.
Task taskCont = tsk.ContinueWith((first) =>
       {
         Console.WriteLine("Продолжение запущено");
         for(int count = 0; count < 5; count++) {
           Thread.Sleep (500);
           Console.WriteLine("В продолжении подсчет равен " + count );
         }
         Console.WriteLine("Продолжение завершено");
       }

В этом фрагменте кода параметр first принимает предыдущую задачу (в данном случае — tsk).

Помимо метода ContinueWith(), в классе Task предоставляются и другие методы, поддерживающие продолжение задачи, обеспечиваемое классом TaskFactory. К их числу относятся различные формы методов ContinueWhenAny() и ContinueWhenAll(), которые продолжают задачу, если завершится любая или все указанные задачи соответственно.

Оглавление книги


Генерация: 3.064. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз