Eu tenho alguns problemas com a resposta principal a esta pergunta.
Em primeiro lugar, em uma situação verdadeira de fogo e esquecimento , você provavelmente não await
executará a tarefa, por isso é inútil anexar ConfigureAwait(false)
. Se você não await
definir o valor retornado por ConfigureAwait
, ele não terá nenhum efeito.
Em segundo lugar, você precisa estar ciente do que acontece quando a tarefa é concluída com uma exceção. Considere a solução simples que @ ade-miller sugeriu:
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
Isso introduz um perigo: se uma exceção não tratada escapa SomeMethod()
, nunca será observado que exceção, e podem 1 seja relançada no segmento finalizador, batendo sua aplicação. Portanto, eu recomendaria usar um método auxiliar para garantir que quaisquer exceções resultantes sejam observadas.
Você poderia escrever algo assim:
public static class Blindly
{
private static readonly Action<Task> DefaultErrorContinuation =
t =>
{
try { t.Wait(); }
catch {}
};
public static void Run(Action action, Action<Exception> handler = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var task = Task.Run(action); // Adapt as necessary for .NET 4.0.
if (handler == null)
{
task.ContinueWith(
DefaultErrorContinuation,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(
t => handler(t.Exception.GetBaseException()),
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Essa implementação deve ter sobrecarga mínima: a continuação só é chamada se a tarefa não for concluída com êxito e deve ser chamada de forma síncrona (em vez de ser agendada separadamente da tarefa original). No caso "preguiçoso", você nem mesmo incorrerá em uma alocação para o delegado de continuação.
Iniciar uma operação assíncrona torna-se trivial:
Blindly.Run(SomeMethod); // Ignore error
Blindly.Run(SomeMethod, e => Log.Warn("Whoops", e)); // Log error
1. Esse era o comportamento padrão no .NET 4.0. No .NET 4.5, o comportamento padrão foi alterado de forma que exceções não observadas não fossem relançadas no encadeamento do finalizador (embora você ainda possa observá-las por meio do evento UnobservedTaskException em TaskScheduler). No entanto, a configuração padrão pode ser substituída e, mesmo se seu aplicativo exigir .NET 4.5, você não deve presumir que as exceções de tarefas não observadas serão inofensivas.