关于 Task.Start() 、 Task.Run() 和 Task.Factory.StartNew() 的用法
Regarding usage of Task.Start() , Task.Run() and 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 为 TPL 中的 运行 工作提供了 3 种不同的方式,因为它们的工作方式相同:Task.Start()
、Task.Run()
和 Task.Factory.StartNew()
。
请问,Task.Start()
、Task.Run()
、Task.Factory.StartNew()
是同一个用途还是有不同的意义?
什么时候用Task.Start()
,什么时候用Task.Run()
,什么时候用Task.Factory.StartNew()
?
请通过示例帮助我根据场景详细了解它们的实际用法,谢谢。
Task.Run
是 shorthand for Task.Factory.StartNew
具有特定的安全参数:
Task.Factory.StartNew(
action,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
它是在 .Net 4.5 中添加的,以帮助 async
的日益频繁的使用和将工作卸载到 ThreadPool
。
Task.Factory.StartNew
(在 .Net 4.0 中随 TPL 添加)更加健壮。你应该只在 Task.Run
不够的时候使用它,例如当你想使用 TaskCreationOptions.LongRunning
时(尽管当代理是异步的时候它是不必要的。更多关于我的博客:LongRunning Is Useless For Task.Run With async-await). More on Task.Factory.StartNew
in Task.Run vs Task.Factory.StartNew
永远不要创建 Task
并调用 Start()
,除非你找到一个非常好的理由这样做。仅当您有一部分需要创建任务但不安排任务而另一部分无需创建即可安排任务时才应使用它。这几乎从来都不是一个合适的解决方案,而且可能很危险。 "Task.Factory.StartNew" vs "new Task(...).Start"
中的更多内容
总之,大多数情况下使用 Task.Run
,如果必须使用 Task.Factory.StartNew
,绝对不要使用 Start
。
简答:
如果您没有使用嵌套children的任务并且总是希望您的任务在线程池上执行最好使用 Task.Run
.
长答案:
Task.Run
和 Task.Factory.StartNew
都支持创建和调度任务 objects 所以我们不需要创建 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
这意味着 children 的任务不能附加到 parent 而它使用 TaskScheduler.Default
这意味着线程池上的 运行s 任务将始终用于 运行 任务。
Task.Factory.StartNew
使用 TaskScheduler.Current
表示当前线程的调度程序,它可能是 TaskScheduler.Default
但并非总是如此。
我刚刚看到 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 为 TPL 中的 运行 工作提供了 3 种不同的方式,因为它们的工作方式相同:Task.Start()
、Task.Run()
和 Task.Factory.StartNew()
。
请问,Task.Start()
、Task.Run()
、Task.Factory.StartNew()
是同一个用途还是有不同的意义?
什么时候用Task.Start()
,什么时候用Task.Run()
,什么时候用Task.Factory.StartNew()
?
请通过示例帮助我根据场景详细了解它们的实际用法,谢谢。
Task.Run
是 shorthand for Task.Factory.StartNew
具有特定的安全参数:
Task.Factory.StartNew(
action,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);
它是在 .Net 4.5 中添加的,以帮助 async
的日益频繁的使用和将工作卸载到 ThreadPool
。
Task.Factory.StartNew
(在 .Net 4.0 中随 TPL 添加)更加健壮。你应该只在 Task.Run
不够的时候使用它,例如当你想使用 TaskCreationOptions.LongRunning
时(尽管当代理是异步的时候它是不必要的。更多关于我的博客:LongRunning Is Useless For Task.Run With async-await). More on Task.Factory.StartNew
in Task.Run vs Task.Factory.StartNew
永远不要创建 Task
并调用 Start()
,除非你找到一个非常好的理由这样做。仅当您有一部分需要创建任务但不安排任务而另一部分无需创建即可安排任务时才应使用它。这几乎从来都不是一个合适的解决方案,而且可能很危险。 "Task.Factory.StartNew" vs "new Task(...).Start"
总之,大多数情况下使用 Task.Run
,如果必须使用 Task.Factory.StartNew
,绝对不要使用 Start
。
简答:
如果您没有使用嵌套children的任务并且总是希望您的任务在线程池上执行最好使用 Task.Run
.
长答案:
Task.Run
和 Task.Factory.StartNew
都支持创建和调度任务 objects 所以我们不需要创建 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
这意味着 children 的任务不能附加到 parent 而它使用 TaskScheduler.Default
这意味着线程池上的 运行s 任务将始终用于 运行 任务。
Task.Factory.StartNew
使用 TaskScheduler.Current
表示当前线程的调度程序,它可能是 TaskScheduler.Default
但并非总是如此。