关于Task.Start(),Task.Run()和Task.Factory.StartNew()的用法


142

我只看到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给出了三种不同的方式在运行第三方物流工作,因为他们所有的工作一样的:Task.Start()Task.Run()Task.Factory.StartNew()

你告诉我,Task.Start()Task.Run()Task.Factory.StartNew()全部用于同一目的,还是他们有不同的意义呢?

什么时候应该使用Task.Start(),什么时候应该使用Task.Run(),什么时候应该使用Task.Factory.StartNew()

请通过示例帮助我详细了解它们根据场景的实际用法,谢谢。


有一篇老文章解释说,这里这里都是较新的Task.Run -也许这会回答您的问题;)
Carsten 2015年

Task.Start实际有用的示例。
noseratio

Answers:


171

Task.RunTask.Factory.StartNew带有特定安全参数的简写:

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

它在.Net 4.5中添加,以帮助日益频繁地使用async和卸载.NET 4.5 ThreadPool

Task.Factory.StartNew(在.Net 4.0中添加了TPL)更加健壮。您仅应在Task.Run不够用的情况下使用它,例如在您想使用时使用TaskCreationOptions.LongRunning(尽管当委托异步时这是不必要的。有关我的博客的更多信息:LongRunning对于Task.Run with async-await是无用的)。更多关于Task.Factory.StartNewTask.Run VS Task.Factory.StartNew

除非找到极好的理由,否则不要创建Taskand呼叫Start()。仅当您有一部分需要创建任务但不计划任务而另一部分计划不创建时才应使用它。那几乎永远不是一个合适的解决方案,并且可能很危险。更多的“Task.Factory.StartNew”与“新任务(......)。开始”

总之,大部分使用 Task.RunTask.Factory.StartNew如果必须且永不使用,请使用Start


5
您说“永远不要创建Task并调用Start()”将我重定向到任何可能表明Task.Start()可能导致的写操作。我需要详细信息,因为您要避免这样做。谢谢您的回复。


1
@Mou Task.Start主要用于继承类型。
Yuval Itzchakov 2015年

1
@Mou效率低下,因为它需要同步以确保仅被调用一次。其他选项则没有。
i3arnon 2015年

2
@Mou您可能应该阅读解释该问题的文章blogs.msdn.com/b/pfxteam/archive/2010/06/13/10024153.aspx
i3arnon

2

简短答案

如果您不使用嵌套的子级任务,并且始终希望在线程池上执行任务,则最好使用Task.Run

长答案:

Task.RunTask.Factory.StartNew两个提供支持创建和调度任务对象,所以我们并不需要创建一个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但并非总是如此。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.