2016-07-17 407 views
53

Ho Metodo:Qual è la differenza tra Task.Run() e Task.Factory.StartNew()

private static void Method() 
{ 
    Console.WriteLine("Method() started"); 

    for (var i = 0; i < 20; i++) 
    { 
     Console.WriteLine("Method() Counter = " + i); 
     Thread.Sleep(500); 
    } 

    Console.WriteLine("Method() finished"); 
} 

E voglio iniziare questo metodo in una nuova attività. Posso iniziare nuovo compito come questo

var task = Task.Factory.StartNew(new Action(Method)); 

o questo

var task = Task.Run(new Action(Method)); 

Ma c'è qualche differenza tra Task.Run() e Task.Factory.StartNew(). Entrambi utilizzano ThreadPool e avviano Method() immediatamente dopo aver creato l'istanza dell'attività. Quando dovremmo usare la prima variante e quando la seconda?

+1

In realtà, StartNew non deve utilizzare il ThreadPool, vedere il blog a cui mi sono collegato nella mia risposta. Il problema è 'StartNew' di default usa' TaskScheduler.Current' che potrebbe essere il pool di thread ma potrebbe anche essere il thread dell'interfaccia utente. –

+0

Possibile duplicato di [Informazioni sull'utilizzo di Task.Start(), Task.Run() e Task.Factory.StartNew()] (https://stackoverflow.com/questions/29693362/regarding-usage-of-task-start -task-run-and-task-factory-startnew) –

risposta

6

Il secondo è stato introdotto nella nuova versione di .NET framework ed è recommended. Il primo ha più opzioni, la seconda è una scorciatoia:

metodo The Run fornisce una serie di sovraccarichi che lo rendono facile per iniziare un task, usando i valori predefiniti. È un'alternativa leggera ai sovraccarichi di StartNew .

E da stenografia intendo una tecnica shortcut:

public static Task Run(Action action) 
{ 
    return Task.InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default, 
     TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark); 
} 
62

Il secondo metodo, Task.Run, è stato introdotto in una versione successiva del framework .NET (in .NET 4.5).

Tuttavia, il primo metodo, Task.Factory.StartNew, offre la possibilità di definire molte cose utili sul thread che si desidera creare, mentre Task.Run non fornisce questo.

Ad esempio, diciamo che si desidera creare un thread di attività a esecuzione prolungata. Se un thread del pool di thread verrà utilizzato per questa attività, questo potrebbe essere considerato un abuso del pool di thread.

Una cosa che si potrebbe fare per evitare questo sarebbe di eseguire l'attività in un thread separato. Una discussione appena creata che sarebbe stata dedicata a questa attività e sarebbe stata distrutta una volta completata l'attività. È Non possibile raggiungere questo obiettivo con la Task.Run, mentre è possibile farlo con il Task.Factory.StartNew, come di seguito:

Task.Factory.StartNew(..., TaskCreationOptions.LongRunning); 

Come si afferma here:

Così, in .NET Framework 4.5 Developer Preview, abbiamo introdotto il nuovo metodo Task.Run . Ciò non obsoletes Task.Factory.StartNew, ma piuttosto dovrebbe semplicemente essere pensato come un modo rapido per utilizzare Task.Factory.StartNew senza bisogno di specificare un gruppo di parametri. È una scorciatoia. In effetti, Task.Run è in realtà implementato in termini della stessa logica utilizzata per Task.Factory.StartNew, passando solo alcuni parametri predefiniti. Quando si passa un'azione a attività.Run:

Task.Run(someAction); 

che è esattamente equivalente a:

Task.Factory.StartNew(someAction, 
    CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); 
+3

Ho un pezzo di codice in cui lo statomente 'che è esattamente equivalente a' non regge. – Emaborsa

+1

@Emaborsa Apprezzerei se potessi pubblicare questo pezzo di codice ed elaborare la tua argomentazione. Grazie in anticipo ! – Christos

+0

Sono 40 loc con alcune dipendenze ... come si fa? – Emaborsa

14

Vedi this blog article che descrive la differenza. Fondamentalmente fare:

Task.Run(A) 

è lo stesso di fare:

Task.Factory.StartNew(A, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); 
-3

Nella mia domanda che chiama due servizi, ho confrontato sia Task.Run e Task.Factory.StartNew. Ho scoperto che nel mio caso funzionano entrambi bene. Tuttavia, il secondo è più veloce.