Как правильно управлять исключением в задаче с помощью ContinueWith

После прочтения информации об управлении задачами и exepcion, я использую этот код для управления исключением, выданным в Задаче:

Task<Object> myTask = Task.Factory.StartNew<Object>(doTask, CancellationToken.None,   TaskCreationOptions.None, TaskScheduler.Default);
myTask .ContinueWith(task => afterTask(task), TaskScheduler.FromCurrentSynchronizationContext());

Где doTask и AfterTask находятся:

private <Object> doTask() {
    throw new Exception("BOOM");
}

private afterTask(Task<Object> aTask) {

        if (aTask.IsFaulted)
        {
            MessageBox.Show(aTask.Exception.InnerException.Message);
        }
        else //whatever
}

Когда генерируется Exception Boom, Visual Studio отображает предупреждение, информирующее о том, что исключение не было перехвачено, но если я продолжу выполнение, исключение будет обработано в функции afterTask.

Правильно ли этот код или я неправильно понял какое-то основное поведение задачи? Есть ли способ избежать предупреждения отладчика о том, что выполнение не было поймано? Это немного раздражает...

заранее спасибо

2 ответа

Решение

Попробуйте это вместо этого:

 task.ContinueWith(
            t =>
            t.Exception.Handle(ex =>
                                   {
                                       logger.Error(ex.Message, ex);
                                       return false;
                                   })

            , TaskContinuationOptions.OnlyOnFaulted
            );

Используя TaskContinuationOptions.OnlyOnFaultedзапускаешь ContinueWith блокировать только если исключение выдается исходной задачей.

Кроме того, вы можете выбрать, возвращать ли true или false из лямбда-выражения, переданного Handle, указывающий, было ли обработано исключение или нет. В моем случае я не хотел, чтобы исключение распространялось. Вы можете изменить его, чтобы вернуть true в твоем случае.

        try
        {
            var t1 = Task.Delay(1000);

            var t2 = t1.ContinueWith(t =>
            {
                Console.WriteLine("task 2");
                throw new Exception("task 2 error");
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

            var t3 = t2.ContinueWith(_ =>
            {
                Console.WriteLine("task 3");
                return Task.Delay(1000);
            }, TaskContinuationOptions.OnlyOnRanToCompletion).Unwrap();

            // The key is to await for ALL tasks rather than just
            // the first or last task.
            await Task.WhenAll(t1, t2, t3);
        }
        catch (AggregateException aex)
        {
            aex.Flatten().Handle(ex =>
                {
                    // handle your exceptions here
                    Console.WriteLine(ex.Message);
                    return true;
                });
        }
Другие вопросы по тегам