Библиотека TPL C#. Задачи продолжения (continuation task)

Задачи продолжения (continuation task) или просто «продолжение» — это такие задачи, которые могут вызываться другой задаче (предшествующей), при завершении этой предшествующей задачи. Использование продолжений позволяет организовать цепочки взаимосвязанных задач и передавать некоторые результаты из одной задачи в другую.

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

В примере, представленном ниже, создается задача продолжения, которая выводит в консоль число увеличенное на 1.

using System;
using System.Threading.Tasks;

namespace Tasks
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = new Task<int>(() => Increment(11) );//создаем предшествующую задачу
            Task continuation = task.ContinueWith(x=>Display(task.Result));//создаем продолжение
            task.Start();//запускаем предшествующую задачу
            continuation.Wait();//ожидаем окончание продолжения
        }
        static void Display(int x)
        {
            Console.WriteLine(x);
        }

        static int Increment(int a)
        { 
            return ++a;
        }
    }
}

Вначале мы создаем предшествующую задачу task, которая должна возвращать нам результат типа int (о возвращаемых результатах задачами см. эту статью). Задача продолжения (continuation) принимает результат от task и выводит в консоль результат. Задача продолжения создается путем вызова метода ContinueWith предшествующей задачи. В качестве параметра,  ContinueWith принимает делегат Action<Task<TResult>>.

В приведенном выше примере представлена простейшая цепочка, состоящая из двух задач: первая задача выполняет сложения, вторая — выводит результат в консоль.

Создание продолжения для нескольких задач

Если необходимо создать продолжение для нескольких задач, то можно воспользоваться одним из следующих статичных методов класса Task:

  • WhenAll — продолжение будет выполнено после завершения всех предшествующих задач
  • WhenAny — продолжение будет выполнено после завершение какой-либо задачи из списка

или аналогичными методами класса TaskFactory:

  • ContinueWhenAll
  • ContinueWhenAny

Рассмотрим следующий пример:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Tasks
{
    internal class Program
    {
        public static void Main()
        {
            var tasks = new List<Task<int>>();
            for (int ctr = 1; ctr <= 10; ctr++)
            {
                int baseValue = ctr;
                tasks.Add(Task.Factory.StartNew(b => (int)b * (int)b, baseValue));
            }

            Task<int[]> results = Task.WhenAll(tasks);

            int sum = 0;
            for (int ctr = 0; ctr <= results.Result.Length - 1; ctr++)
            {
                var result = results.Result[ctr];
                Console.Write($"{result} {((ctr == results.Result.Length - 1) ? "=" : "+")} ");
                sum += result;
            }

            Console.WriteLine(sum);
        }
    }
}

Для создания задачи продолжения (results) вызывается статичный метод Task.WhenAll(). Продолжение отражает результаты десяти своих предшествующих задач, каждой из которых соответствует значение индекса в диапазоне от 1 до 10. Если предшествующие задачи завершаются успешно (их свойство Task.Status имеет значение RanToCompletion), то свойство Result продолжения представляет собой массив значений Task<TResult>.Result , возвращенных каждой предшествующей задачей. Затем рассчитывается сумма квадратов чисел от 1 до 10 и выводится в консоль:

1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100 = 385

Итого

Сегодня мы рассмотрели ещё один момент использования библиотеки TPL в .NET C# — задачи продолжения. Используя задачи продолжения мы можем создавать цепочки задач, в которых результаты следующих задач (продолжений) могут основываться на результатах предшествующих задач. Для создания задач продолжения мы можем использовать статичные методы класса Task или метод ContinueWith.

Подписаться
Уведомить о
guest
2 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии