Per quanto riguarda l'utilizzo di Task.Start (), Task.Run () e Task.Factory.StartNew ()


143

Ho appena visto 3 routine relative all'uso di TPL che fanno lo stesso lavoro; ecco il codice:

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Create a task and supply a user delegate by using a lambda expression. 
    Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
    // Start the task.
    taskA.Start();

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                  Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Define and run the task.
    Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                      Thread.CurrentThread.Name);
    taskA.Wait();
}

public static void Main()
{
    Thread.CurrentThread.Name = "Main";

    // Better: Create and start the task in one operation. 
    Task taskA = Task.Factory.StartNew(() => Console.WriteLine("Hello from taskA."));

    // Output a message from the calling thread.
    Console.WriteLine("Hello from thread '{0}'.", 
                    Thread.CurrentThread.Name);

    taskA.Wait();                  
}

Io proprio non capisco perché MS dà 3 modi diversi per eseguire i lavori in TPL, perché tutto il lavoro lo stesso: Task.Start(), Task.Run()e Task.Factory.StartNew().

Dimmi, sei Task.Start(), Task.Run()e Task.Factory.StartNew()tutti utilizzati per lo stesso scopo o hanno un significato diverso?

Quando si dovrebbe usare Task.Start(), quando si dovrebbe usare Task.Run()e quando si dovrebbe usare Task.Factory.StartNew()?

Ti prego, aiutami a capire il loro reale utilizzo come da scenario in dettaglio con esempi, grazie.


c'è un vecchio articolo che spiega che qui e qui per il nuovoTask.Run - forse questo risponderà alla tua domanda;)
Carsten

Ecco un esempio di dove Task.Startè effettivamente utile.
noseratio,

Risposte:


171

Task.Runè una scorciatoia per Task.Factory.StartNewargomenti specifici sicuri:

Task.Factory.StartNew(
    action, 
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

È stato aggiunto in .Net 4.5 per facilitare l'utilizzo asynce lo scaricamento sempre più frequente del lavoro su ThreadPool.

Task.Factory.StartNew(aggiunto con TPL in .Net 4.0) è molto più robusto. Dovresti usarlo solo se Task.Runnon è abbastanza, ad esempio quando vuoi usarlo TaskCreationOptions.LongRunning(anche se non è necessario quando il delegato è asincrono. Maggiori informazioni sul mio blog: LongRunning è inutile per Task.Run With async-waitit ). Altro su Task.Factory.StartNewin Task.Run vs Task.Factory.StartNew

Non creare mai Taske chiamare a Start()meno che non trovi un motivo estremamente valido per farlo. Dovrebbe essere usato solo se hai una parte che deve creare attività ma non le pianifichi e un'altra parte che pianifica senza creare. Questa non è quasi mai una soluzione appropriata e potrebbe essere pericolosa. Altro in "Task.Factory.StartNew" vs "new Task (...). Start"

In conclusione, usa principalmente Task.Run, usa Task.Factory.StartNewse devi e non usare mai Start.


5
hai detto "Non creare mai un'attività e chiama Start ()" reindirizzami a qualsiasi buona scrittura che mostrerà ciò che potrebbe causare Task.Start (). ho bisogno di dettagli perché stai dicendo di evitarlo. grazie per la risposta.
Mou,


1
@Mou Task.Startha il suo posto per ereditare principalmente i tipi.
Yuval Itzchakov,

1
@Mou È inefficiente in quanto richiede la sincronizzazione per assicurarsi che venga chiamato solo una volta. Le altre opzioni no.
i3arnon,

2
@Mou Probabilmente dovresti leggere il post che spiega questo problema blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

Risposta breve :

Se non si utilizzano attività per bambini nidificati e si desidera sempre che le attività vengano eseguite nel pool di thread , è meglio utilizzarle Task.Run.

Risposta lunga:

Task.Runed Task.Factory.StartNewentrambi forniscono supporto per la creazione e la pianificazione di oggetti Task, quindi non è necessario creare un Taske chiamareStart()

Task.Run(action);

È equivalente a:

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

E

Task.Factory.StartNew(action);

È equivalente a:

Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);

Task.Runusa il TaskCreationOptions.DenyChildAttachche significa che le attività dei bambini non possono essere associate al genitore e usa il TaskScheduler.Defaultche significa che quello che esegue le attività nel pool di thread verrà sempre utilizzato per eseguire le attività.

Task.Factory.StartNewusa il TaskScheduler.Currentche significa che lo scheduler del thread corrente, potrebbe essere, TaskScheduler.Defaultma non sempre.

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.