Creazione di thread - Task.Factory.StartNew vs new Thread ()


102

Sto solo imparando a conoscere le nuove librerie Threading e Parallel in .Net 4

In passato avrei creato un nuovo thread in questo modo (come esempio):

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

Adesso posso fare:

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

Qual è la differenza se esiste?

Grazie


1
Dovrai preoccuparti un po 'di come funziona lo scheduler del pool di thread. Può fare una grande differenza, ma tutto dipende da ciò che fai effettivamente all'interno del thread.
Hans Passant

Risposte:


79

C'è una grande differenza. Le attività sono pianificate nel ThreadPool e potrebbero anche essere eseguite in modo sincrono se appropriato.

Se si dispone di un lungo lavoro in background, è necessario specificarlo utilizzando l'opzione Attività corretta.

Dovresti preferire Task Parallel Library rispetto alla gestione esplicita dei thread, poiché è più ottimizzata. Inoltre hai più funzionalità come Continuazione.


5
No, non lo fa. Inizia solo le attività. Ciò potrebbe accodare l'attività nel pool di thread o eseguirla in modo sincrono. Il TPL ti libera dalla gestione dei thread / concorrenza da solo e dall'utilizzo del meglio per la tua piattaforma (come l'utilizzo dei core)
sanosdole

10
C'è l'opzione TaskCreationOptions.LongRunning che creerà sempre un altro thread, ma il punto è perché hai bisogno di un altro thread? Se vuoi solo fare qualcosa in parallelo (Main fa qc. Mentre Task è in esecuzione) è preferibile lasciare che una libreria ottimizzata decida come utilizzare le risorse di sistema come i thread per farlo nel modo più efficiente.
sanosdole

3
Questo articolo di msdn descrive come vengono pianificate le attività. Copre longrunning e inlining (esecuzione sincrona). msdn.microsoft.com/en-us/library/dd997402.aspx
sanosdole

2
@sming Il punto è che si desidera elaborare contemporaneamente (senza bloccare l'interfaccia utente), non che si desidera un nuovo thread. ThreadPool non bloccherà il thread dell'interfaccia utente, ma gestirà i thread in background in modo molto più efficiente di quanto si possa fare manualmente creando thread. Questo è il cambiamento nel processo mentale introdotto dal TPL. Non pensare ai thread, pensa alle attività simultanee.
sanosdole

4
@sming Scusa, quella frase era un po 'troppo grossolana. L'esecuzione sincrona delle attività è chiamata inlining. Quando si pianifica un'attività sul threadpool (scheduler predefinito) dal thread dell'interfaccia utente, non si verificherà. Si verificherà solo se l'utilità di pianificazione ambientale ("TaskScheduler.Current") è uguale all'utilità di pianificazione di un'attività su cui si chiama ".Wait ()". Poiché ".Wait ()" sta bloccando, bloccherà comunque l'interfaccia utente. Breve: non chiamare wait e non verrà eseguito in modo sincrono.
sanosdole

74

L'attività ti dà tutta la bontà dell'API dell'attività:

  • Aggiunta di continuazioni ( Task.ContinueWith)
  • In attesa del completamento di più attività (tutte o alcune)
  • Catturare gli errori nell'attività e interrogarli in seguito
  • Acquisizione della cancellazione (e possibilità di specificare la cancellazione con cui iniziare)
  • Potenzialmente con un valore di ritorno
  • Utilizzo di await in C # 5
  • Migliore controllo sulla pianificazione (se sarà di lunga durata, dillo quando crei l'attività in modo che l'utilità di pianificazione possa tenerne conto)

Tieni presente che in entrambi i casi puoi semplificare leggermente il codice con le conversioni del gruppo di metodi:

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

8
+1. Vorrei aggiungere che Threadè di livello molto basso rispetto a Task(ho un post sul blog che va nei dettagli). Sto facendo una specie di discorso " Usare Tasks nel mondo reale" al Grand Rapids DevDay . Il discorso si chiama "Thread is Dead", perché non ce n'è più bisogno Thread(a meno che tu non stia implementando a TaskScheduler).
Stephen Cleary

@StephenCleary, presumo che intendi dire che Threadè morto, quando si tratta di essere utilizzato come thread in background?
declino

1
@ebb: No, prendo la posizione più forte descritta nel mio primo commento. Non c'è niente che Threadpossa fare (o BackgroundWorker) che non possa essere fatto in modo più elegante Taske appropriato TaskScheduler.
Stephen Cleary

1
@StephenCleary, come creeresti un thread dedicato, senza utilizzarlo Thread?
riflusso

4
@ebb: "Thread dedicato" non mi è chiaro. Se vuoi che un Taskvenga eseguito su un thread specifico, usa un appropriato TaskScheduler- ad es AsyncContextThread. Tuttavia, questo di solito non è necessario; il SynchronizationContext, ThreadPool, e ConcurrentExclusiveSchedulerPairpianificatori sono sufficienti per la maggior parte dei programmi.
Stephen Cleary

12

Nel primo caso stai semplicemente iniziando un nuovo thread mentre nel secondo caso stai entrando nel pool di thread.

Il lavoro del pool di thread consiste nel condividere e riciclare i thread. Permette di evitare di perdere qualche millisecondo ogni volta che occorre creare un nuovo thread.

Esistono diversi modi per accedere al pool di thread:

  • con il TPL (Task Parallel Library) come hai fatto tu
  • chiamando ThreadPool.QueueUserWorkItem
  • chiamando BeginInvoke su un delegato
  • quando usi un BackgroundWorker

1

Il tuo primo blocco di codice dice a CLR di creare un Thread (diciamo. T) per te che può essere eseguito come sfondo (usa i thread del pool di thread durante la pianificazione di T). In breve, chiedi esplicitamente a CLR di creare un thread per farti fare qualcosa e chiama il metodo Start () sul thread per iniziare.

Il secondo blocco di codice fa lo stesso ma delega (implicitamente il passaggio di consegne) la responsabilità di creare il thread (in background, che viene nuovamente eseguito nel pool di thread) e il thread di avvio tramite il metodo StartNew nell'implementazione di Task Factory.

Questa è una rapida differenza tra determinati blocchi di codice. Detto questo, ci sono poche differenze dettagliate che puoi cercare su Google o vedere altre risposte dai miei colleghi collaboratori.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.