Связывание задач в C#

Связывание задач в C#

Всем доброго времени суток. На связи Алексей Гулынин. В прошлой статье мы говорили про PLINQ в C#. В данной статье я бы хотел рассказать о том, как связать задачи (Tasks) в C#. Иногда может возникнуть ситуация, когда нужно связать различные задачи между собой. Например, имеется 2 задачи: выполнение второй задачи должно начаться сразу после выполнения первой. Мы не хотим выполнять их в основном потоке. Это можно сделать с помощью статического метода класса "Task" — "ContinueWith()".

Давайте сразу на примере разберем, как это работает. Первая задача будет возращать строку, а во второй задаче мы будем эту строку использовать:

using System;
using System.Text;
using System.Threading.Tasks;
namespace TestApplicationForStudy
{
  class Program
  {
    static void Main(string[] args)
    {
      Task<string> firstTask = new Task<string>(() => "Alex");
      // Создаём вторую задачу
      Task<string> secondTask = firstTask.ContinueWith((firstResult) => 
                                String.Format("Привет, {0}", firstTask.Result));
      // Запускаем только первую задачу, вторая запустится автоматически
      firstTask.Start();
      Console.WriteLine(secondTask.Result);
      Console.ReadLine();
    }
  }
}

Вложенные задачи ("Nested Tasks")

В коде одной задачи можно запускать другие задачи. Возникает вопрос: будет ли внешняя задача ждать, пока завершится внутренняя? — Ответ: не будет. Они будут выполняться параллельно. На следующем примере цифрами отметил порядок отображения сообщений в консоли:

static void Main(string[] args)
{
  Task outerTask = Task.Run(() =>
  {
    Console.WriteLine("Запустилась внешняя задача!"); //1
    Task innerTask = Task.Run(() =>
    {
      Console.WriteLine("Запустилась внутренняя задача!"); //3
      Console.WriteLine("Внутренняя задача завершилась..."); //4
    });       
  });
  outerTask.Wait();
  Console.WriteLine("Внешняя задача завершилась..."); //2
  Console.ReadLine();
}

Можно сделать так, чтобы внешняя задача дождалась завершения внутренней. Изменим предыдущий пример. В метод "Run()" нужно добавить ещё один параметр. Первый — это делегат, второй — "TaskCreationOptions.AttachedToParent". Если мы сейчас запустим, то изменится порядок вывода:

static void Main(string[] args)
{
  var outerTask = Task.Factory.StartNew(() =>
  {
    Console.WriteLine("Запустилась внешняя задача!"); //1
    var innerTask = Task.Factory.StartNew( () =>
    {
      Console.WriteLine("Запустилась внутренняя задача!"); //2
      // Прерываем выполнение потока на 5 секунд
      Thread.Sleep(5000);
      Console.WriteLine("Внутренняя задача завершилась..."); //3
     }, TaskCreationOptions.AttachedToParent);
   });
   outerTask.Wait();
   Console.WriteLine("Внешняя задача завершилась..."); //4
   Console.ReadLine();
}

В данном случае образуется иерархия задач. Такая иерархия, при которой одна задача запускает другую, называется "родительская-дочерняя" иерархия.

В данной небольшой статье вы узнали о том, как связать задачи (Tasks) в C#.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.


Комментарии:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *