Skip to main content

Task.Run e Task.Factory.StarNew | Threads | CSharp

  • Task.Run e Task.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ísticaTask.RunTask.Factory.StartNew
Facilidade de usoSimples e diretoMais complexo e configurável
Executa no ThreadPoolSimDepende das opções
Compatível com async/awaitSimNão recomendado
FlexibilidadeBaixaAlta (permite configurações)
Ideal paraProcessamento paralelo curtoTarefas 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 com async/await.
  • Task.Factory.StartNew deve ser usado apenas se precisar de controle avançado sobre a execução da tarefa.
  • Se precisar de tarefas longas, prefira Task.Run ou Task.Factory.StartNew com TaskCreationOptions.LongRunning.