Относительно использования 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 бесполезен для Task.Run с async-await). Еще Task.Factory.StartNew в Task.Run vs Task.Factory.StartNew

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

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

Краткий ответ:

Если вы не используете вложенные дочерние задачи и всегда хотите, чтобы ваши задачи выполнялись в пуле потоков, лучше использоватьTask.Run.

Длинный ответ:

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

Task.Run(action);

Эквивалентно:

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

А также

Task.Factory.StartNew(action);

Эквивалентно:

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

Task.Run использует TaskCreationOptions.DenyChildAttach Это означает, что детские задачи не могут быть привязаны к родительскому объекту, и он использует TaskScheduler.Default Это означает, что тот, который выполняет задачи в пуле потоков, всегда будет использоваться для выполнения задач.

Task.Factory.StartNew использует TaskScheduler.Current что означает планировщик текущего потока, это может быть TaskScheduler.Default но не всегда.

Другие вопросы по тегам