创建线程 - Task.Factory.StartNew vs new Thread()

Jon*_*Jon 99 .net c# multithreading .net-4.0

我刚学习.Net 4中新的线程和并行库

在过去,我会像这样创建一个新线程(作为示例):

DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThread.IsBackground = true;
DataInThread.Start();
Run Code Online (Sandbox Code Playgroud)

现在我能做到:

Task t = Task.Factory.StartNew(() =>
{
   ThreadProcedure();
});
Run Code Online (Sandbox Code Playgroud)

有什么区别?

谢谢

san*_*ole 78

有一个很大的不同.任务在ThreadPool上安排,如果合适,甚至可以执行同步.

如果您有长时间运行的后台工作,则应使用正确的任务选项指定此项.

您应该更喜欢任务并行库而不是显式线程处理,因为它更加优化.此外,您还有更多功能,如Continuation.

  • 有一个TaskCreationOptions.LongRunning选项,它将始终创建另一个线程,但重点是为什么你需要另一个线程?如果您只想并行执行某些操作(主要是在执行任务时执行),最好让优化的库决定如何利用线程等系统资源以最有效的方式执行此操作. (10认同)
  • 那么StartNew不保证单独的线程? (7认同)
  • 不,不.它只是启动任务.这可以将任务排入线程池或同步执行.TPL旨在让您自己管理线程/并发,并为您的平台使用最佳(如使用内核) (5认同)
  • @sming抱歉,那句话有点太粗糙了.任务的同步执行称为内联.从UI线程调度线程池(默认调度程序)上的任务时,它不会发生.只有当环境调度程序('TaskScheduler.Current')与您调用'.Wait()'的任务的调度程序相同时,才会发生这种情况.由于'.Wait()'正在阻止,它无论如何都会阻止UI.短:不要等待,它不会同步执行. (4认同)
  • 这篇msdn文章描述了如何安排任务.它涵盖了长运行和内联(同步执行).http://msdn.microsoft.com/en-us/library/dd997402.aspx (3认同)
  • @sming的重点是您要同时处理(不阻塞UI),而不是想要新线程。ThreadPool不会阻止UI线程,但是管理后台线程比通过创建线程手动执行要高效得多。这就是TPL引入的思维过程的变化。不要想线程,要考虑并发任务。 (2认同)

Jon*_*eet 73

该任务为您提供了任务API的所有优点:

  • 添加延续(Task.ContinueWith)
  • 等待完成多项任务(全部或任何)
  • 捕获任务中的错误并在以后查询它们
  • 捕获取消(并允许您指定取消开始)
  • 可能具有回报价值
  • 在C#5中使用await
  • 更好地控制调度(如果它将长时间运行,在创建任务时这样说,以便任务调度程序可以将其考虑在内)

请注意,在这两种情况下,您都可以使用方法组转换使代码更简单:

DataInThread = new Thread(ThreadProcedure);
// Or...
Task t = Task.Factory.StartNew(ThreadProcedure);
Run Code Online (Sandbox Code Playgroud)

  • +1.我想补充说,与'Task`相比,`Thread`是非常低级的(我有一个[博客文章](http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous .html)详细说明).我在[Grand Rapids DevDay](http://grdevday.org/)上发表了"在现实世界中使用任务"的演讲.这个谈话被称为"Thread is Dead",因为不再需要`Thread`(除非你实现了`TaskScheduler`). (8认同)
  • @ebb:"Dedicated thread"对我来说并不清楚.如果你想在特定的线程上运行`Task`,那么使用适当的`TaskScheduler` - 例如,[`AsyncContextThread`](http://nitoasyncex.codeplex.com/wikipage?title=AsyncContextThread).但是,这通常不是必需的; `SynchronizationContext`,`ThreadPool`和`ConcurrentExclusiveSchedulerPair`调度程序足以满足大多数程序的需要. (4认同)

ale*_*kow 12

在第一种情况下,您只是启动一个新线程,而在第二种情况下,您正在进入线程池.

线程池的工作是共享和回收线程.它允许每次我们需要创建一个新线程时避免丢失几毫秒.

有几种方法可以进入线程池:

  • 像你一样使用TPL(任务并行库)
  • 通过调用ThreadPool.QueueUserWorkItem
  • 通过在委托上调用BeginInvoke
  • 当您使用BackgroundWorker时