Относительно использования 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
но не всегда.