Thread.Start() 与 ThreadPool.QueueUserWorkItem()
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) 是否有任何特殊原因?
- 性能原因?
- 图案?
- 最好的方法是什么?
我感觉答案是:“视情况而定”。您能否列出一种方法优于另一种方法的一些情况?
The Microsoft .NET Base Class Library provides several ways to create a thread and start it. 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.
Well, there are two approaches (essentially):
1) Using the 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.
ThreadPool.QueueUserWorkItem(myfunction, new Object()); /* Same philosophy here */
Are there any special reasons why I should use 1) or 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
启动新线程可能是一项非常昂贵的操作。线程池重用线程,从而摊销成本。除非您需要专用线程,否则建议使用线程池。通过使用专用线程,您可以更好地控制线程特定属性,例如优先级、区域性等。此外,您不应该在线程池上执行长时间运行的任务,因为这会迫使池生成额外的线程。
除了您提到的选项之外,.NET 4 还提供了一些很棒的并发抽象。查看 Task 和 Parallel 类以及所有新的 PLINQ 方法。
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. 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. Check out the Task and Parallel classes as well as all the new PLINQ methods.
托管线程池对于何时不使用线程池。
根据我的经验,当您需要持久的、专用的、长时间运行的线程时,您希望创建自己的线程。对于其他一切,请使用异步委托或诸如 QueueUserWorkItem 、BackgroundWorker 或 .NET 4.0 的任务相关功能之类的东西。
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.ThreadPool中的线程是后台线程;
由新 Thread 对象创建和启动的所有线程都是前台线程。
后台线程不会使托管执行环境保持运行。
请参阅 http://msdn.microsoft.com/en-us/library/h339syd0 .aspx 了解更多。
Threads in ThreadPool are background threads;
All threads created and started by a new Thread object are foreground threads.
A background thread does not keep the managed execution environment running.
refer to http://msdn.microsoft.com/en-us/library/h339syd0.aspx for more.
在 .NET 4.5.2 中,他们添加了一个新方法:HostingEnvironment.QueueBackgroundWorkItem。
这似乎是 ThreadPool.QueueUserWorkItem 的替代方案。两者的行为相似,但在 ASP.NET 中使用新方法有一些很好的好处:
In .NET 4.5.2 they added a new method: HostingEnvironment.QueueBackgroundWorkItem.
This appears to be an alternative to
ThreadPool.QueueUserWorkItem
. Both behave similarly, but there are some nice benefits to using the new method when working in ASP.NET:使用ThreadPool,您对线程系统的控制较少。这是为您简化流程的权衡。如果您从线程池中获得了所需的一切,您应该随意使用它。如果您需要对线程进行更多控制,那么您当然需要使用 Thread 类。
Using the ThreadPool, you have less control of the threading system. 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. If you need more control of the threads, then you need to of course use the Thread classes.
ThreadPool.QueueUserWorkItem() 基本上适用于“即发即忘”场景,即应用程序不依赖于操作是否完成。
使用经典线程进行细粒度控制。
ThreadPool.QueueUserWorkItem() is basically for fire-and-forget scenarios, when application doesn't depend on whether operations will finish or not.
Use classic threads for fine-grained control.
您应该使用 ThreadPool.QueueUserWorkItem,除非出现以下情况:
您需要前台线程。
您需要一个线程具有特定的优先级。
您的任务会导致线程长时间阻塞
时间。线程池有最大线程数,所以很大
阻塞线程池线程的数量可能会阻止任务
正在启动。
您需要将线程放入单线程单元中。全部
ThreadPool 线程位于多线程单元中。
你需要有一个与线程相关联的稳定身份,或者
将线程专用于任务。
参考 链接。
You should use
ThreadPool.QueueUserWorkItem
except in cases of: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.
You need to have a stable identity associated with the thread, or to
dedicate a thread to a task.
Reference link.