Что касается использования Task.Start(), Task.Run() и Task.Factory.StartNew()

Я только что видел 3 процедуры, касающиеся использования TPL, которые выполняют ту же работу; вот код:

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

Я просто не понимаю, почему MS предоставляет 3 разных способа запуска заданий в TPL, потому что все они работают одинаково: Task.Start(), Task.Run() и Task.Factory.StartNew().

Скажите, все ли Task.Start(), Task.Run() и Task.Factory.StartNew() используются для одной и той же цели или они имеют разное значение?

Когда следует использовать Task.Start(), когда следует использовать Task.Run() и когда следует использовать Task.Factory.StartNew()?

Пожалуйста, помогите мне понять их реальное использование в соответствии со сценарием очень подробно с примерами, спасибо.

Ответ 1

Task.Run является сокращением для Task.Factory.StartNew с конкретными безопасными аргументами:

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

Он был добавлен в .Net 4.5 для помощи во все более частом использовании async и перегрузке работы на ThreadPool.

Task.Factory.StartNew (добавлен с TPL в .Net 4.0) гораздо более надежен. Вы должны использовать его, только если Task.Run недостаточно, например, когда вы хотите использовать TaskCreationOptions.LongRunning (хотя это и не нужно, когда делегат асинхронный. Подробнее об этом в моем блоге: LongRunning Is Useless For Task. Запустить с асинхронным ожиданием). Подробнее о Task.Factory.StartNew в Task.Run vs Task.Factory.StartNew

Никогда не создавайте Task и не звоните Start(), если вы не найдете для этого очень веских причин. Его следует использовать, только если у вас есть какая-то часть, которая должна создавать задачи, но не запланировать их, а другая часть, которая планирует без создания. Это почти никогда не подходящее решение и может быть опасным. Подробнее о "Task.Factory.StartNew" и "новой задаче (...). Запуск"

В заключение, в основном используйте Task.Run, используйте Task.Factory.StartNew, если вы должны и никогда не используете Start.

Ответ 2

В дополнение к Ответу, вы не должны создавать задачу из конструктора без веской причины. TPL берет на себя большую осторожность при синхронизации и concurrency. Скрыть эту сложность от клиентского кода. Если вы создадите задачу и запустите ее, вам нужно подумать о синхронизации и concurrency, которые, очевидно, трудно обрабатывать.