Связывание задач в 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#.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.