Tratamento de exceções em tarefas C#

Resumo : neste tutorial você aprenderá como tratar exceções geradas pela operação assíncrona executada pelos Taskobjetos.

Introdução à AggregateException

Em geral, quando Taskencontra uma exceção, ele a propaga para o thread de chamada. Se a Taskcontiver tarefas aninhadas, quaisquer operações assíncronas executadas nessas tarefas também poderão resultar no lançamento de várias exceções.

Para propagar todas as exceções para o thread de chamada, Taskenvolva-as em um AggregateExceptionobjeto.

O AggregateExceptionobjeto possui a InnerExceptionspropriedade que contém todas as exceções originais. A InnerExceptionsé uma coleção somente leitura das Exceptioninstâncias.

Para tratar essas exceções, você pode enumerá-las através da InnerExceptionspropriedade do AggregateExceptionobjeto usando um foreachloop.

Alternativamente, você pode lidar com as exceções originais usando o AggregateException.Handlemétodo:

public void Handle (Func<Exception,bool> predicate);Linguagem de código:  PHP  ( php )

É importante observar que agrupará Tasktodas as exceções que ocorrerem em um AggregationExceptionobjeto, mesmo que uma única exceção seja gerada.

Exemplo de tratamento de AggregateException

O programa a seguir ilustra como lidar com exceções em uma operação assíncrona executada por uma tarefa.

decimal Divide(decimal a, decimal b)
{
    Thread.Sleep(1000);

    return a / b;
}

try
{
    var task = Task.Run(() => Divide(10, 0));
    var result = task.Result;
}
catch (AggregateException ae)
{
    ae.Flatten().Handle(e =>
    {
        if (e is DivideByZeroException)
        {
            Console.WriteLine(e.Message);
            return true;
        }
        else
        {
            throw e;
        }
    });
}Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, defina um método Divide()que receba dois números decimais e retorne o resultado da divisão deles após um atraso de um segundo:

decimal Divide(decimal a, decimal b)
{
    Thread.Sleep(1000);

    return a / b;
}Linguagem de código:  C#  ( cs )

Segundo, use o Task.Run()método para executar o Divide()método de forma assíncrona em um thread separado. Como usamos os argumentos 10 e 0, o Divide()método lançará uma DivideByZeroExceptionexceção:

var task = Task.Run(() => Divide(10, 0));Linguagem de código:  C#  ( cs )

Terceiro, use o bloco try…catch para capturar quaisquer exceções lançadas pelo método. Como a operação assíncrona lança um AggregateException, nós o capturamos e tratamos no catchbloco.

No manipulador de exceções, usamos o Handle()método da AggregateExceptionclasse para tratar cada exceção interna.

Se a exceção for DivideByZeroException, o programa enviará a mensagem de erro para o console. Caso contrário, ele relançará a mesma exceção.

Ao executar o programa, você verá a seguinte saída:

Attempted to divide by zero.Linguagem de código:  C#  ( cs )

Resumo

  • Use o try...catchpara capturar o AggregateExceptionlançado pela operação assíncrona executada por um Task.
  • Use o AggregateException.Handle()método para lidar com exceções.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *