Quero desencadear uma tarefa para executar em um thread em segundo plano. Não quero esperar a conclusão das tarefas.
No .net 3.5, eu teria feito isso:
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
No .net 4, o TPL é a maneira sugerida. O padrão comum que eu vi recomendado é:
Task.Factory.StartNew(() => { DoSomething(); });
No entanto, o StartNew()
método retorna um Task
objeto que implementa IDisposable
. Isso parece ser esquecido pelas pessoas que recomendam esse padrão. A documentação do MSDN sobre o Task.Dispose()
método diz:
"Sempre chame Dispose antes de liberar sua última referência para a tarefa."
Você não pode chamar a disposição em uma tarefa até que ela seja concluída, portanto, fazer com que o encadeamento principal aguarde e descarte a chamada acabaria com o ponto de execução em um encadeamento em segundo plano. Também não parece haver nenhum evento concluído / finalizado que possa ser usado para limpeza.
A página MSDN na classe Task não comenta isso, e o livro "Pro C # 2010 ..." recomenda o mesmo padrão e não faz nenhum comentário sobre o descarte de tarefas.
Eu sei que se eu deixar o finalizador irá pegá-lo no final, mas isso vai voltar e me morder quando estou fazendo muito fogo e esquecer tarefas como essa e o encadeamento do finalizador ficar sobrecarregado?
Então, minhas perguntas são:
- É aceitável não chamar
Dispose()
aTask
turma neste caso? E se sim, por que e há riscos / consequências? - Existe alguma documentação que discuta isso?
- Ou existe uma maneira apropriada de descartar o
Task
objeto que perdi? - Ou existe outra maneira de fazer fogo e esquecer tarefas com o TPL?