Em relação ao uso de Task.Start (), Task.Run () e Task.Factory.StartNew ()

143

Acabei de ver três rotinas sobre o uso do TPL que fazem o mesmo trabalho; aqui está o código:

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();                  
}

Eu só não entendo por que MS dá 3 maneiras diferentes de executar trabalhos em TPL porque todos eles trabalham o mesmo: Task.Start(), Task.Run()e Task.Factory.StartNew().

Diga-me, são Task.Start(), Task.Run()e Task.Factory.StartNew()todos utilizados para a mesma finalidade ou eles têm um significado diferente?

Quando se deve usar Task.Start(), quando se deve usar Task.Run()e quando se deve usar Task.Factory.StartNew()?

Por favor, ajude-me a entender seu uso real conforme o cenário em detalhes, com exemplos, obrigado.

Mou
fonte
existe um artigo antigo explicando que aqui e aqui para os mais novosTask.Run - talvez isso responda à sua pergunta;)
Carsten
Aqui está um exemplo de onde Task.Starté realmente útil.
Noseratio 17/04

Respostas:

171

Task.Runé uma abreviação de Task.Factory.StartNewargumentos seguros específicos:

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

Foi adicionado no .Net 4.5 para ajudar no uso cada vez mais frequente asynce no trabalho de descarregamento para o ThreadPool.

Task.Factory.StartNew(adicionado com o TPL no .Net 4.0) é muito mais robusto. Você deve usá-lo apenas se Task.Runnão for suficiente, por exemplo, quando quiser usá- TaskCreationOptions.LongRunninglo (embora seja desnecessário quando o delegado for assíncrono. Mais sobre isso no meu blog: LongRunning é inútil para tarefas.Executar com async-waitit ). Mais sobre Task.Factory.StartNewem Task.Run vs Task.Factory.StartNew

Nunca crie uma Taskchamada e a Start()menos que encontre um motivo extremamente bom para fazê-lo. Só deve ser usado se você tiver uma parte que precise criar tarefas, mas não agendá-las, e outra parte que agendar sem criar. Isso quase nunca é uma solução apropriada e pode ser perigoso. Mais em "Task.Factory.StartNew" vs "new Task (...). Start"

Em conclusão, principalmente use Task.Run, useTask.Factory.StartNew se você precisar e nunca use Start.

i3arnon
fonte
5
você disse: "Nunca crie uma tarefa e chame Start ()" me redireciona para qualquer boa redação que mostre que isso pode causar o Task.Start (). Eu preciso de detalhes porque ur dizendo para evitá-lo. Obrigado pela resposta.
Mou
1
O @Mou Task.Starttem seu lugar para herdar tipos principalmente.
Yuval Itzchakov 17/04/2015
1
@Mou É ineficiente, pois requer sincronização para garantir que seja chamado apenas uma vez. As outras opções não.
I3arnon 17/04/2015
2
@Mou Você provavelmente deve ler o post que explica esta questão blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon
2

Resposta curta :

Se você não estiver usando tarefas filho aninhadas e sempre desejar que suas tarefas sejam executadas no Pool de Threads , é melhor usá-lo Task.Run.

Resposta longa:

Task.Rune Task.Factory.StartNewambos fornecem suporte para criar e agendar objetos de tarefas, para que não precisemos criar Taske chamarStart()

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 o TaskCreationOptions.DenyChildAttachque significa que as tarefas dos filhos não podem ser anexadas ao pai e usa o TaskScheduler.Defaultque significa que aquele que executa tarefas no Conjunto de Threads sempre será usado para executar tarefas.

Task.Factory.StartNewusa o TaskScheduler.Currentque significa planejador do encadeamento atual, pode ser, TaskScheduler.Defaultmas nem sempre.

Ali Bayat
fonte