Task.Run e Task.Factory.StarNew | Threads | CSharp
Task.RuneTask.Factory.StarNew| Threads | CSharp
Tanto Task.Factory.StartNew quanto Task.Run são usados para iniciar tarefas assíncronas em C#, mas possuem diferenças importantes que podem impactar a forma como as tarefas são agendadas e executadas. Vamos explorar essas diferenças e entender quando usar cada um.
Task.Run
Task.Run é o método mais comum para executar código de forma assíncrona no ThreadPool. Ele é recomendado para a maioria dos cenários onde você deseja simplesmente rodar uma tarefa em background.
Exemplo: Executando uma Task no ThreadPool
Task.Run(() =>
{
Console.WriteLine("Executando no ThreadPool");
Thread.Sleep(2000);
});
Características do Task.Run
✔ Executa no ThreadPool (uso eficiente de threads).
✔ Ideal para tarefas curtas e não bloqueantes.
✔ Simples e direto para código assíncrono.
✔ Automaticamente usa TaskScheduler.Default.
❌ Não é flexível para configuração avançada (ex: Long Running, Attached Child, etc.).
Cenário recomendado
- Quando precisa rodar tarefas curtas e paralelas (ex: processar uma lista em paralelo).
- Quando deseja desacoplar a execução de um código sem bloquear a thread principal.
Task.Factory.StartNew
Task.Factory.StartNew é um método mais avançado e flexível que permite personalizar a criação da Task, como definir opções específicas de agendamento, preferências de criação de threads e comportamentos de encadeamento.
Exemplo: Criando uma Task com comportamento personalizado
Task.Factory.StartNew(() =>
{
Console.WriteLine("Executando com StartNew");
Thread.Sleep(2000);
});
Porém, o código acima pode ter problemas se você estiver trabalhando com async/await. O StartNew não entende bem o async/await e pode não se comportar como esperado.
Características do Task.Factory.StartNew
✔ Permite configuração avançada via TaskCreationOptions.
✔ Melhor controle sobre o agendamento da Task.
✔ Pode ser executado como tarefa "Long Running", evitando o uso do ThreadPool.
✔ Útil para cenários onde precisa de controle sobre o encadeamento de tarefas.
❌ Não lida bem com async/await (pode não aguardar corretamente a conclusão da Task).
❌ Pode criar um overhead desnecessário se usado para cenários simples.
Comparação entre Task.Run e Task.Factory.StartNew
| Característica | Task.Run | Task.Factory.StartNew |
|---|---|---|
| Facilidade de uso | Simples e direto | Mais complexo e configurável |
| Executa no ThreadPool | Sim | Depende das opções |
| Compatível com async/await | Sim | Não recomendado |
| Flexibilidade | Baixa | Alta (permite configurações) |
| Ideal para | Processamento paralelo curto | Tarefas que precisam de controle avançado |
Quando Usar Cada Um?
Use Task.Run quando:
✔ Você quer executar código assíncrono sem bloquear a thread principal.
✔ Você está lidando com tarefas curtas e não bloqueantes.
✔ Você precisa de suporte adequado para async/await.
Use Task.Factory.StartNew quando:
✔ Você precisa de mais controle sobre a execução da Task (ex: Task Long Running).
✔ Você precisa de configurações avançadas como TaskCreationOptions.
✔ Você está lidando com tarefas CPU-bound que não devem usar o ThreadPool.
Exemplo de Task.Factory.StartNew com Configuração Avançada
Se precisar de um processo pesado que não deve ser executado no ThreadPool, pode usar:
Task.Factory.StartNew(() =>
{
Console.WriteLine("Executando com Long Running Task");
Thread.Sleep(5000);
}, TaskCreationOptions.LongRunning);
Aqui, a Task será executada em uma thread separada do ThreadPool.
Conclusão
Task.Runé mais simples e funciona bem para a maioria dos casos comasync/await.Task.Factory.StartNewdeve ser usado apenas se precisar de controle avançado sobre a execução da tarefa.- Se precisar de tarefas longas, prefira
Task.RunouTask.Factory.StartNewcomTaskCreationOptions.LongRunning.