Книга: 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()
, которые продолжают задачу, если завершится любая или все указанные задачи соответственно.
- Два подхода к параллельному программированию
- Класс Task
- Применение методов ожидания
- Применение класса TaskFactory для запуска задачи
- Применение лямбда-выражения в качестве задачи
- Создание продолжения задачи
- Возврат значения из задачи
- Отмена задачи и обработка исключения AggregateException
- Другие средства организации задач
- Класс Parallel
- Исследование возможностей PLINQ
- Создание файлов с блокировкой
- Создание свободно позиционируемых элементов
- 1.1. Информатика. Предмет информатики. Основные задачи информатики
- Повторяющиеся задачи
- 12. Лекция: Создание приложений с графическим интерфейсом пользователя.
- Постановка задачи
- Создание объектов Collection
- 7.4.2.4. Создание своего первого LiveCD
- 4.2. Создание трехмерной модели и построение горизонтальной проекции детали
- 7.4.2. Создание собственного LiveCD
- Создание пользователя и группы на рабочей станции
- Создание корня документа: