При ожидании завершения задачи с помощью метода Wait(), или свойства Result, любое необработанное исключение будет передано вызывающему коду, а именно объекту AggregationException, что делает не обязательным обработку исключений внутри самой задачи:
int x = 0;
Task<int> z = Task.Factory.StartNew (() => 10 / x);
try
{
Console.WriteLine (calc.Result);
}
catch (AggregateException aex)
{
Console.Write (aex.InnerException.Message);
}
Но все же необходимо обрабатывать исключения автономных задач (т.е задач, которые не являются родительскими для других задач, и завершения, выполнения которых никто не ожидает).
увеличить изображение
Рис. 7.5. Результат выполнения программы с обработкой исключения
Отмена выполнения задач
Отмена выполнения заданий осуществляется с помощью специальных маркеров отмены (token). Структура CancellationToken - распространяет уведомление о том, что операции следует отменить. При запуске задачи можно передать маркер отмены, что позволит отменить выполнение задачи:
CancellationTokenSource cancelSource = new CancellationTokenSource();
CancellationToken token = cancelSource.Token;
Task task = Task.Factory.StartNew (() =>
{
token.ThrowIfCancellationRequested(); // Проверяем запрос отмены
}, token);
...
cancelSource.Cancel();
Для отмененной задачи вызывается исключение - AggregateException, которое необходимо обработать и проверить следующим образом:
try
{
task.Wait();
}
catch (AggregateException ex)
{
if (ex.InnerException is OperationCanceledException)
Console.Write ("Задание отменено");
}
увеличить изображение
Рис. 7.6. Результат выполнения программы с использованием отмены задачи
Продолжения
Для того что бы упорядочить выполнение задач в программе, т.е. к примеру что бы Задача 3 выполнялась сразу же после выполнения Задачи 2, а Задача 2 после завершения Задачи 1, необходимо использовать методContinueWith() класса - Task. Форма объявление данного метода представлена ниже:
public Task ContinueWith(Action<Task>)
Пример работы метода ContinueWith() представлен ниже:
Task task1 = Task.Factory.StartNew (() => Console.Write ("Hello "));
Task task2 = task1.ContinueWith (main => Console.Write ("World!"));
где main - аргумент, который передается в задачу-продолжение в лямбда-выражении, является ссылкой на родительскую задачу.
увеличить изображение
Рис. 7.7. Результат выполнения программы с использование метода ContinueWith()
Продолжения и Task <TResult>
В классе Task<TResult>, также можно использовать продолжение и возвращать некоторые данные, с использованием последовательности вычисления:
Task.Factory.StartNew<int>(() => 10)
.ContinueWith(main => main.Result * 2)
.ContinueWith(main => Math.Sqrt(main.Result))
.ContinueWith(main => Console.WriteLine(main.Result));
увеличить изображение
Рис. 7.8. Результат выполнения программы с использование продолжения в классе Task<TResult>