Thread.Start()与ThreadPool.QueueUserWorkItem()

时间:2011-05-31 20:03:35

标签: c# .net multithreading threadpool

Microsoft .NET基类库提供了几种创建线程并启动它的方法。基本上,调用与提供相同类型服务的每个其他调用非常相似:创建表示执行流(或更多)的对象,为其分配表示要执行的执行流的委托,并最终根据委托签名,对象作为参数。

嗯,有两种方法(基本上):

1)使用System.Threading.Thread类。

Thread curr = new Thread(myfunction); /* In a class, myfunction is a void taking an object */
curr.Start(new Object()); /* Or something else to be downcast */

2)使用System.Threading.ThreadPool类。

ThreadPool.QueueUserWorkItem(myfunction, new Object()); /* Same philosophy here */

我应该使用1)或2)有什么特殊原因吗?

  • 表现原因?
  • 模式?
  • 什么是最好的方法?

我有一种感觉,答案是:“视情况而定”。能否列举一些方法比另一种更好的情况?

7 个答案:

答案 0 :(得分:46)

启动新线程可能是一项非常昂贵的操作。线程池重用线程,从而摊销成本。除非您需要专用线程,否则建议使用线程池。通过使用专用线程,您可以更好地控制特定于线程的属性,例如优先级,文化等。此外,您不应该在线程池上执行长时间运行的任务,因为它会强制池生成其他线程。

除了你提到的选项之外,.NET 4还提供了一些很好的并发抽象。查看Task和Parallel类以及所有新的PLINQ方法。

答案 1 :(得分:12)

The Managed Thread Pool在不使用线程池时有一些非常好的指导。

根据我的经验,您需要在需要持久,专用,长时间运行的线程时创建自己的线程。对于其他所有内容,请使用异步委托或类似QueueUserWorkItemBackgroundWorker或.NET 4.0的任务相关功能。

答案 2 :(得分:7)

ThreadPool中的线程是后台线程; 由新Thread对象创建和启动的所有线程都是前台线程。

后台线程不会使托管执行环境继续运行。

请参阅http://msdn.microsoft.com/en-us/library/h339syd0.aspx了解更多信息。

答案 3 :(得分:6)

在.NET 4.5.2中,他们添加了一种新方法:HostingEnvironment.QueueBackgroundWorkItem

这似乎是ThreadPool.QueueUserWorkItem的替代方案。两者的行为相似,但在ASP.NET中使用新方法有一些很好的好处:

  

HostingEnvironment.QueueBackgroundWorkItem方法可以让你   安排小背景工作项目。 ASP.NET跟踪这些项目和   防止IIS突然终止工作进程,直到所有   后台工作项目已完成。无法调用此方法   在ASP.NET托管应用程序域之外。

答案 4 :(得分:2)

使用ThreadPool,您可以减少对线程系统的控制。这是为您简化流程的权衡。如果您拥有ThreadPool所需的全部功能,您应该随意使用它。如果你需要更多的线程控制,那么你当然需要使用Thread类。

答案 5 :(得分:1)

ThreadPool.QueueUserWorkItem()基本上适用于即发即弃的场景,当应用程序不依赖于操作是否完成时。

使用经典线程进行细粒度控制。

答案 6 :(得分:0)

除以下情况外,您应使用ThreadPool.QueueUserWorkItem

  • 您需要一个前台线程。

  • 您需要一个线程具有特定的优先级。

  • 您有一些任务导致线程长时间阻塞 时间。线程池具有最大线程数,因此很大 被阻止的线程池线程数可能会阻止任务执行 开始。

  • 您需要将线程放入单线程单元中。所有 ThreadPool线程位于多线程单元中。

  • 您需要具有与线程关联的稳定身份,或者 将线程专用于任务。

参考link