简体   繁体   English

Thread.Start() 与 ThreadPool.QueueUserWorkItem()

[英]Thread.Start() versus ThreadPool.QueueUserWorkItem()

The Microsoft .NET Base Class Library provides several ways to create a thread and start it. Microsoft .NET Base Class 库提供了多种创建线程和启动线程的方法。 Basically the invocation is very similar to every other one providing the same kind of service: create an object representing an execution flow (or more), assign it a delegate representing the execution flow to execute and, eventually, depending on delegate signature, an object as a parameter.基本上,调用与提供相同类型服务的所有其他调用非常相似:创建一个代表执行流(或更多)的 object,为其分配一个代表要执行的执行流的委托,最终,根据委托签名,一个 object作为参数。

Well, there are two approaches (essentially):好吧,有两种方法(基本上):

1) Using the System.Threading.Thread class. 1) 使用System.Threading.Thread class。

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) Using the System.Threading.ThreadPool class. 2) 使用System.Threading.ThreadPool class。

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

Are there any special reasons why I should use 1) or 2)?我应该使用 1) 或 2) 有什么特殊原因吗?

  • Performance reasons?性能原因?
  • Patterns?模式?
  • What is the best approach?最好的方法是什么?

I have a feeling that the answer is: "Depend by the situation".我感觉答案是:“视情况而定”。 Could you please list some situations where one approach is better than another?您能否列出一些情况,其中一种方法比另一种更好?

Starting a new thread can be a very expensive operation.启动一个新线程可能是一项非常昂贵的操作。 The thread pool reuses threads and thus amortizes the cost.线程池重用线程,从而摊销成本。 Unless you need a dedicated thread, the thread pool is the recommended way to go.除非您需要专用线程,否则线程池是 go 的推荐方式。 By using a dedicated thread you have more control over thread specific attributes such as priority, culture and so forth.通过使用专用线程,您可以更好地控制线程特定属性,例如优先级、文化等。 Also, you should not do long running tasks on the thread pool as it will force the pool to spawn additional threads.此外,您不应该在线程池上执行长时间运行的任务,因为它会强制池产生额外的线程。

In addition to the options you mention .NET 4 offers some great abstractions for concurrency.除了您提到的选项之外,.NET 4 还提供了一些出色的并发抽象。 Check out the Task and Parallel classes as well as all the new PLINQ methods.查看 Task 和 Parallel 类以及所有新的 PLINQ 方法。

The Managed Thread Pool has some very good guidelines on when NOT to use the thread pool.托管线程池对何时不使用线程池有一些很好的指导。

In my experience, you want to create your own thread when you need a persistent, dedicated, long-running thread.以我的经验,当你需要一个持久的、专用的、长时间运行的线程时,你想创建自己的线程。 For everything else, use asynchronous delegates or something like QueueUserWorkItem , BackgroundWorker , or the Task-related features of .NET 4.0.对于其他一切,使用异步委托或类似QueueUserWorkItemBackgroundWorker或 .NET 4.0 的任务相关功能。

Threads in ThreadPool are background threads; ThreadPool 中的线程是后台线程; All threads created and started by a new Thread object are foreground threads.由新线程 object 创建和启动的所有线程都是前台线程。

A background thread does not keep the managed execution environment running.后台线程不会使托管执行环境保持运行。

refer to http://msdn.microsoft.com/en-us/library/h339syd0.aspx for more.有关更多信息,请参阅http://msdn.microsoft.com/en-us/library/h339syd0.aspx

In .NET 4.5.2 they added a new method: HostingEnvironment.QueueBackgroundWorkItem .在 .NET 4.5.2 中,他们添加了一个新方法: HostingEnvironment.QueueBackgroundWorkItem

This appears to be an alternative to ThreadPool.QueueUserWorkItem .这似乎是ThreadPool.QueueUserWorkItem的替代方案。 Both behave similarly, but there are some nice benefits to using the new method when working in ASP.NET:两者的行为相似,但在 ASP.NET 中工作时使用新方法有一些不错的好处:

The HostingEnvironment.QueueBackgroundWorkItem method lets you schedule small background work items. HostingEnvironment.QueueBackgroundWorkItem 方法允许您安排小型后台工作项。 ASP.NET tracks these items and prevents IIS from abruptly terminating the worker process until all background work items have completed. ASP.NET 跟踪这些项目并防止 IIS 在所有后台工作项目完成之前突然终止工作进程。 This method can't be called outside an ASP.NET managed app domain.不能在 ASP.NET 托管应用程序域之外调用此方法。

Using the ThreadPool, you have less control of the threading system.使用 ThreadPool,您可以减少对线程系统的控制。 This is a trade off to simplify the process for you.这是为您简化流程的权衡。 If you have all that you need from the ThreadPool, you should feel free to utilize it.如果您从 ThreadPool 中获得了所需的一切,那么您应该可以随意使用它。 If you need more control of the threads, then you need to of course use the Thread classes.如果您需要更多地控制线程,那么您当然需要使用 Thread 类。

ThreadPool.QueueUserWorkItem() is basically for fire-and-forget scenarios, when application doesn't depend on whether operations will finish or not. ThreadPool.QueueUserWorkItem() 基本上适用于即发即弃的场景,当应用程序不依赖于操作是否完成时。

Use classic threads for fine-grained control.使用经典线程进行细粒度控制。

You should use ThreadPool.QueueUserWorkItem except in cases of:您应该使用ThreadPool.QueueUserWorkItem除非以下情况:

  • You require a foreground thread.您需要一个前台线程。

  • You require a thread to have a particular priority.您需要一个线程具有特定的优先级。

  • You have tasks that cause the thread to block for long periods of time.您的任务会导致线程长时间阻塞。 The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.线程池具有最大线程数,因此大量阻塞的线程池线程可能会阻止任务启动。

  • You need to place threads into a single-threaded apartment.您需要将线程放入单线程单元中。 All ThreadPool threads are in the multithreaded apartment.所有 ThreadPool 线程都在多线程单元中。

  • You need to have a stable identity associated with the thread, or to dedicate a thread to a task.您需要有一个与线程相关联的稳定身份,或者将线程专用于某项任务。

Reference link .参考链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM