Criando threads - Task.Factory.StartNew vs new Thread ()


102

Estou começando a aprender sobre as novas bibliotecas Threading e Parallel em .Net 4

No passado, eu criaria um novo Thread como este (como exemplo):

DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThread.IsBackground = true;
DataInThread.Start();

Agora posso fazer:

Task t = Task.Factory.StartNew(() =>
{
   ThreadProcedure();
});

Qual é a diferença se houver?

obrigado


1
Você precisará se preocupar um pouco sobre como funciona o agendador de pool de threads. Pode fazer uma grande diferença, mas tudo depende do que você realmente faz dentro do tópico.
Hans Passant

Respostas:


79

Há uma grande diferença. As tarefas são agendadas no ThreadPool e podem até ser executadas de forma síncrona, se apropriado.

Se você tiver um trabalho em segundo plano de longa execução, deverá especificá-lo usando a opção de tarefa correta.

Você deve preferir a Biblioteca Paralela de Tarefas em vez do tratamento de thread explícito, pois é mais otimizada. Além disso, você tem mais recursos como Continuação.


5
Não, não importa. Ele apenas inicia tarefas. Isso pode enfileirar a tarefa no pool de threads ou executá-la de forma síncrona. O TPL trata de liberar você do gerenciamento de threads / simultaneidade e usar o melhor para sua plataforma (como a utilização de núcleos)
sanosdole,

10
Existe a opção TaskCreationOptions.LongRunning que sempre criará outro encadeamento, mas a questão toda é por que você precisa de outro encadeamento? Se você deseja apenas fazer algo em paralelo (Main faz sth. Enquanto Task é executado), é preferível deixar uma biblioteca otimizada decidir como utilizar recursos do sistema, como threads, para fazer isso da maneira mais eficiente.
sanosdole

3
Este artigo msdn descreve como as tarefas são agendadas. Abrange longgrunning e inlining (execução síncrona). msdn.microsoft.com/en-us/library/dd997402.aspx
sanosdole

2
@sming O ponto é que você deseja processar simultaneamente (não bloqueando a IU), não que deseja um novo thread. O ThreadPool não bloqueará o thread de IU, mas gerenciará os threads de segundo plano de maneira muito mais eficiente do que você poderia fazer manualmente criando threads. Esse é o processo de mudança de mentalidade que o TPL introduz. Não pense em tópicos, pense em tarefas simultâneas.
sanosdole

4
@sming Desculpe, essa frase foi um pouco grosseira. A execução síncrona de tarefas é chamada de inlining. Ao agendar uma tarefa no threadpool (agendador padrão) do UI Thread, ela não ocorrerá. Isso só ocorrerá se o agendador de ambiente ('TaskScheduler.Current') for o mesmo que o agendador de uma tarefa que você chama de '.Wait ()'. Como '.Wait ()' está bloqueando, ele bloqueará a IU de qualquer maneira. Curto: Não chame esperar e não será executado de forma síncrona.
sanosdole

74

A tarefa oferece todas as vantagens da API de tarefa:

  • Adicionando continuações ( Task.ContinueWith)
  • Esperando que várias tarefas sejam concluídas (todas ou qualquer uma)
  • Capturar erros na tarefa e interrogá-los posteriormente
  • Capturando o cancelamento (e permitindo que você especifique o cancelamento para começar)
  • Possivelmente tendo um valor de retorno
  • Usando o await em C # 5
  • Melhor controle sobre o agendamento (se for demorado, diga isso ao criar a tarefa para que o agendador de tarefas possa levar isso em consideração)

Observe que, em ambos os casos, você pode tornar seu código um pouco mais simples com conversões de grupo de métodos:

DataInThread = new Thread(ThreadProcedure);
// Or...
Task t = Task.Factory.StartNew(ThreadProcedure);

8
+1. Eu gostaria de acrescentar que Threadé um nível muito baixo em comparação com Task(tenho uma postagem no blog que entra em detalhes). Estou dando uma palestra do tipo "usando tarefas no mundo real" no Grand Rapids DevDay . A conversa é chamada de "Thread is Dead", porque não há mais necessidade de Thread(a menos que você esteja implementando um TaskScheduler).
Stephen Cleary,

@StephenCleary, suponho que você quer dizer Threadestá morto, quando se trata de ser usado como um thread de segundo plano?
vazante

1
@ebb: Não, eu assumo a posição mais forte descrita em meu primeiro comentário. Não há nada a Threadfazer (ou BackgroundWorker) que não possa ser feito de forma mais elegante Taske apropriada TaskScheduler.
Stephen Cleary,

1
@StephenCleary, Como você criaria um tópico dedicado, sem usar Thread?
vazante

4
@ebb: "Tópico dedicado" não está claro para mim. Se você deseja que um Taskseja executado em um thread específico, use um apropriado TaskScheduler- por exemplo AsyncContextThread,. No entanto, isso geralmente não é necessário; o SynchronizationContext, ThreadPool, e ConcurrentExclusiveSchedulerPairprogramadores são suficientes para a maioria dos programas.
Stephen Cleary,

12

No primeiro caso, você está simplesmente iniciando um novo encadeamento, enquanto no segundo caso está entrando no pool de encadeamentos.

O trabalho do pool de threads é compartilhar e reciclar threads. Isso permite evitar a perda de alguns milissegundos cada vez que precisamos criar um novo thread.

Existem várias maneiras de entrar no pool de threads:

  • com a TPL (Task Parallel Library) como você fez
  • chamando ThreadPool.QueueUserWorkItem
  • chamando BeginInvoke em um delegado
  • quando você usa um BackgroundWorker

1

Seu primeiro bloco de código diz ao CLR para criar um Thread (digamos. T) para você, que pode ser executado como plano de fundo (use threads do pool de threads ao agendar T). Em suma, você pede explicitamente ao CLR para criar um thread para você fazer algo e chamar o método Start () no thread para iniciar.

Seu segundo bloco de código faz o mesmo, mas delega (entrega implicitamente) a responsabilidade de criar o encadeamento (segundo plano - que novamente é executado no pool de encadeamentos) e o encadeamento inicial por meio do método StartNew na implementação do Task Factory.

Esta é uma diferença rápida entre determinados blocos de código. Dito isso, existem poucas diferenças detalhadas que você pode pesquisar no Google ou ver outras respostas de meus colegas colaboradores.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.