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




