День сто восемьдесят пятый. #ЗаметкиНаПолях
Многопоточность.
5. Задания. Продолжение
Автоматический запуск задания по завершении предыдущего
Вызов метода
Кроме того, вызвать
-
-
-
-
-
-
Вывод результата в предыдущем примере можно переписать с этими флагами:
Если необходим набор заданий в одном состоянии и с одинаковыми параметрами, можно создать фабрику заданий
Продолжение следует…
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 26.
- https://docs.microsoft.com/dotnet/api/system.threading.tasks.task.factory
Многопоточность.
5. Задания. Продолжение
Автоматический запуск задания по завершении предыдущего
Вызов метода
Wait
или свойства Result
при незавершённом задании скорее всего приведёт к блокировке текущего потока и появлению в пуле нового потока. Чтобы этого не происходило, можно переписать код из предыдущих примеров так, чтобы результат выводился в новом задании, которое стартует после завершения предыдущего:var t = new Task<int>((n) => Calc((int)n), 10000);При этом поток, исполняющий этот код и ожидающий завершения каждого из этих заданий, не блокируется, а выполняет другую работу или возвращается в пул. Поскольку метод
t.Start();
Task cwt = t.ContinueWith(task => Console.WriteLine($"Результат: {task.Result}"));
ContinueWith
также возвращает Task
, то и к нему, в свою очередь, можно применять Wait
, Result
или ContinueWith
.Кроме того, вызвать
ContinueWith
можно с флагами TaskContinuationOptions
. Наиболее интересные из них:-
AttachedToParent
– присоединяет задание к родительскому (родительское задание не закончится, пока не исполнятся все дочерние)-
ExecuteSynchronously
– новое задание будет выполнено тем же потоком, что и предыдущее-
OnlyOnCanceled
– выполнять, если предыдущее задание отменено-
OnlyOnFaulted
– выполнять, если предыдущее задание привело к ошибке-
OnlyOnRanToCompletion
– выполнять, если предыдущее задание завершилось успешно-
NotOnCanceled
, NotOnFaulted
, NotOnRanToCompletion
– соответствующие отрицательные флаги.Вывод результата в предыдущем примере можно переписать с этими флагами:
t.ContinueWith(task =>Фабрики заданий
Console.WriteLine($"Результат: {task.Result}"),
TaskContinuationOptions.OnlyOnRanToCompletion);
t.ContinueWith(task =>
Console.WriteLine($"Ошибка: {task.Exception}"),
TaskContinuationOptions.OnlyOnFaulted);
t.ContinueWith(task =>
Console.WriteLine("Операция отменена"),
TaskContinuationOptions.OnlyOnCanceled);
Если необходим набор заданий в одном состоянии и с одинаковыми параметрами, можно создать фабрику заданий
TaskFactory
:string[] files = nullВ коде выше создаётся новая фабрика заданий. Ей можно передать общий токен отмены, параметры создания и продолжения заданий и т.п. Далее задания создаются вызовом метода
string[] dirs = null;
string docsDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var tf = new TaskFactory();
var tasks = new[]
{
tf.StartNew(() => files = Directory.GetFiles(docsDir)),
tf.StartNew(() => dirs = Directory.GetDirectories(docsDir))
};
tf.ContinueWhenAll(tasks, completed => {
Console.WriteLine("{0} содержит: ", docsDir);
Console.WriteLine(" {0} папок", dirs.Length);
Console.WriteLine(" {0} файлов", files.Length);
});
StartNew
. Впоследствии можно добавить задание-продолжение по окончании всех или любого из заданий, вызвав соответственно ContinueWhenAll
или ContinueWhenAny
. В примере выше в фабрике заданий два параллельных задания подсчитывают количество папок и файлов в папке «Мои документы» текущего пользователя, а после завершения всех заданий результаты выводятся в консоль.Продолжение следует…
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 26.
- https://docs.microsoft.com/dotnet/api/system.threading.tasks.task.factory