Tarefa.WhenAny e de Inobservância de Exceções
-
12-12-2019 - |
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).
Solução
O que acontece quando os dois restantes tarefas lançar uma exceção?
Aqueles Task
s 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.