Pergunta

Vamos dizer que eu tenho três tarefas, a, b, e c.Todos os três são garantidos para lançar uma exceção em um tempo aleatório entre 1 e 5 segundos.Eu, então, escrever o seguinte código:

await Task.WhenAny(a, b, c);

Isto acabará por lançar uma exceção a partir de qualquer tarefa de falhas em primeiro lugar.Já que não há nenhum try...catch aqui, essa exceção será bolha até algum outro lugar no meu código.

O que acontece quando os dois restantes tarefas lançar uma exceção?Não são estes inobservância de exceções, o que fará com que todo o processo para ser morto?Isso significa que a única maneira de usar WhenAny é dentro de um try...catch bloquear e, em seguida, de alguma forma, observar os dois restantes tarefas antes de continuar?

Acompanhamento: Eu gostaria que a resposta para aplicar tanto .NET 4.5 e .NET 4.0 com o Assíncrono de Segmentação Pack (embora claramente usando TaskEx.WhenAny em que caso).

Foi útil?

Solução

O que acontece quando os dois restantes tarefas lançar uma exceção?

Aqueles Tasks será concluída em um estado de falha.

Não são estes inobservância de exceções, o que fará com que todo o processo para ser morto?

Não mais.

Em .NET 4.0, o Task o processo de destruição teria de passar a sua inobservância de exceção TaskScheduler.UnobservedTaskException, que iria encerrar o processo, se não tratada.

Em .NET 4.5, este o comportamento foi alterado.Agora, inobservância de exceções passado para TaskScheduler.UnobservedTaskException, mas, em seguida, eles são ignorados se não tratada.

Outras dicas

Sim, os restantes de tarefas exceções são blindado.Pré .NET 4.5, você é obrigado a observá-los (não sei como a situação está ativado .NET 4.5, mas isso mudou).

Eu costumo escrever-me um método auxiliar para o fogo-e-esqueça tarefas como essas:

    public static void IgnoreUnobservedExceptions(this Task task)
    {
        if (task.IsCompleted)
        {
            if (task.IsFaulted)
            {
                var dummy = task.Exception;
            }
            return;
        }

        task.ContinueWith(t =>
            {
                var dummy = t.Exception;
            }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
    }

Você pode querer incluir o registo na produção de aplicativos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top