2009-11-21 37 views
54

正如在.NET 4.0中看到的一样,他们已经添加了一个新的名称空间System.Threading.Tasks,它基本上就是什么意思,一个任务。我只用了几天,从使用ThreadPool。C# - ThreadPool vs任务

哪一个更高效,更少资源消耗? (或只是更好的整体?)

+8

我认为任务使用ThreadPool。 – leppie 2009-11-21 06:12:03

回答

21

Tasks命名空间的目标是提供一个可插拔的体系结构,使多任务应用程序易于编写和更灵活。

该实现使用一个TaskScheduler对象来控制任务的处理。这有虚拟方法,您可以重写以创建自己的任务处理。方法包括例如

protected virtual void QueueTask(Task task) 
public virtual int MaximumConcurrencyLevel 

会有一个小的开销,使用缺省实现有围绕.NET线程实现的包装,但我不希望它是巨大的。

有一个自定义TaskScheduler的实现(草稿)实现多个任务在单个线程here

+8

所有非常真实的,但我不认为任务类的主要目的或吸引力是自定义调度程序。这是一个非常专业化的功能,在某些情况下是非常宝贵的,但大多数用户永远不会碰它。 – 2009-11-21 23:40:40

19

哪一个更有效率更低 资源消耗?

不相干的,会有很小的差别。

(或只是更好的整体)

Task类将是更容易使用的,因为它提供了一个非常干净的界面,用于启动和连接螺纹,并传送例外。它还支持(有限)形式的负载平衡。

+4

任务是在.NET中使用Parallel框架的一种更简单的方法。线程直接从操作系统中获取并立即运行,消耗更多的CPU时间,并且通常不允许框架管理上下文切换和优化技术。这类似于一个孩子扔TANTRUM和尖叫我想现在!对比等待轮到他的人。 – 2013-12-26 14:44:02

+0

@MickeyPerlstein。在我看来,你使用THREADS的描述并不真正适用于线程池(类ThreadPool),这是OP询问的。我同意任务是利用多个CPU的更有效方法,特别是对于高级场景,但对于简单情况下'ThreadPool.QueueUserWorkItem'似乎完全适用。注释? – ToolmakerSteve 2016-05-16 22:56:49

+0

@ToolmakerSteve使用一个系统,好好学习。任务是ms建议的。 QueueUserWorkItem有太多怪癖,这就是为什么他们首先发明了这些任务。这是“承诺”范例 – 2016-11-21 16:24:02

4

另一个值得考虑的关于任务的好处是,当你使用ThreadPool时,你没有任何方法来中止或等待正在运行的线程(除非你在线程的方法中手动执行),但使用这是可能的。如果我错了,请纠正我的错误

+2

AFAIK你不能放弃一个任务,你可以尝试并取消它,但在我的经验,并不总是工作...作为线程。Abort()例如 - 一个工作总是:) – argh 2011-05-04 23:19:07

+4

实际上,您可以使用cancellationtoken来取消线程池和任务。请参阅clr via c# – DarthVader 2012-02-23 05:24:45

5

调度是并行任务的一个重要方面。

与线程不同,新任务不一定立即开始执行。相反,他们被放置在工作队列中。任务在其关联的任务调度程序将其从队列中移除时运行,通常在核心可用时运行。任务调度程序通过控制系统的并发程度来尝试优化整体吞吐量。只要有足够的任务并且任务足够不依赖序列化,程序的性能就会随着可用内核的数量而变化。通过这种方式,任务体现潜在的并行

的概念,我在MSDN上http://msdn.microsoft.com/en-us/library/ff963549.aspx

+0

ThreaPool也是一样,它们又是怎样的不同? – sam 2014-10-22 13:13:50

+1

好点,我猜它只是更多的句法糖。 – 2014-10-27 17:08:05

0

主题

裸机的事情,你可能并不需要使用它,你大概可以使用LongRunning任务,并受益于它的设施。

任务

线程上方的抽象使用线程池(除非您将任务指定为LongRunning操作,如果是这样,则新的线程在你的引擎盖下创建)。

线程池

,顾名思义:线程池。 .NET框架是否为您处理有限数量的线程。为什么?因为在只有8个内核的CPU上打开100个线程来执行昂贵的CPU操作绝对不是一个好主意。该框架将为您维护该池,重用线程(不在每个操作中创建/杀死它们),并且以CPU不会刻录的方式并行执行它们中的一部分。

好的,但何时使用每一个?

恢复中:始终使用任务。

任务是一个抽象,所以它使用起来更容易。我建议你总是尝试使用任务,如果你面临一些问题,使得你需要自己处理一个线程(可能是1%的时间),然后使用线程。

但是要注意:

  • I/O密集型:对于I/O密集型操作(数据库调用,读/写文件,API的调用等)从不使用正常任务,使用如果需要,可以使用任务或线程,但不是正常的任务。因为这会导致你有一些线程繁忙的线程池,还有很多其他任务正在等待轮到池。
  • CPU绑定:对于CPU绑定操作只需使用正常的任务,并很高兴。
+0

关于避免I/O任务的建议显然是错误的。任务完美适用于I/O绑定操作,并受到'async'和'await'的鼓励。 – 2017-10-20 13:58:29

+0

即使是一个相关主题'async'和'await'这里也没有讨论。但是,无论如何,他们不会为I/O操作加入“ThreadPool线程”(正常任务)。我建议你从@StephenCleary中查看[this](https://stackoverflow.com/a/14902702/890890)回答,他在那里详细介绍了它。在他的两个例子中,他没有使用Task.Run()(这会产生一个在另一个上下文中执行的线程池线程)。其他答案也非常有帮助。 – fabriciorissetto 2017-10-20 19:26:42