任务和线程之间有什么区别?

25

今天我在使用TPL时发现了一个新类Task。我想知道Task和Thread的区别是什么,它们哪个更好?

5个回答

62

任务和线程之间有什么区别?

假设您正在运营一家书籍快递公司。您有四辆车和四个司机。一辆车是一个线程,一个司机是一个处理器,而一本书的交付则是一个任务。您面临的问题是如何有效地安排司机和车辆,以便尽快完成任务。

当汽车(线程)多于司机(处理器)时,情况就会变得奇怪起来。这时司机会在旅途的中途停车(暂停线程)并进入另一辆车(切换上下文),驾驶那辆车并执行任务,最终回到第一辆车。显然,这不如让一个司机留在一辆车里高效。

任务并行的思想是将工作分解为小型任务,这些任务可以未来产生结果,然后有效地分配与处理器数量相同的线程,以避免浪费时间在上下文切换上。实际上,通常情况下并不那么完美,但这就是这个想法。

任务和线程哪个更好?

这个问题不能回答,因为它没有任何意义。哪个更好,交付给客户的书还是用来交付书的车?一辆车是一个可以用来交付书籍的设备;这两个事物不能明智地描述为“比”或“不如”另一个。这就像问“哪个更好,洞还是钻?”


5
哪个更好,任务(task)还是线程(thread)?我认为 OP 的意思是相比于使用线程(thread)本身,使用 Thread 类与使用 Task<T> 的区别。 - Aliostad
8
很好的比喻。我以前从未见过如此清晰地解释过。 - Robert Levy
2
如果我们谈论任务和线程,那么你是对的,但如果我们谈论Task和Thread类,那么你是错的 :) 因为这些类彼此之间并没有太大的区别。 - Harry
2
@santosh 就我个人而言,我认为您可以忽略 Lippert 先生的最后一段。.NET 4.0 最重要的功能之一是包含了任务并行库(TPL),原因很简单。1)它简化了创建和使用多个线程。2)它自动利用多个处理器。在您使用 TPL 之前仍然需要熟悉线程,但一旦您熟悉了它,我会坚持使用 TPL,因为它可以让您的很多事情更加容易。 - Hans Rudel
3
@HansRudel:我并没有否认TPL很棒,所以让我明确一点:TPL非常棒。它非常擅长解决某种类型的问题。但是没有人说出他们想要解决的具体问题,因此我无法给出普遍的建议。说“总是使用任务”或“永远不要使用线程”都是愚蠢的;有些问题TPL非常擅长代表您解决,而有些问题则需要您对单个工作线程进行低级别控制。 - Eric Lippert
显示剩余6条评论

18

"任务"是一项将在未来执行并完成的工作。

"线程"是执行某事物的方式。

通常情况下,当您创建一个任务时,默认情况下(即使用Task.Factory.StartNew),该Task会被安排在ThreadPool线程上的某个时间点运行。然而,并非总是如此。

这种分离的优势在于允许框架(或者如果您使用自定义的TaskScheduler)控制您的工作如何映射到可用的线程。通常情况下,您可能会有比线程更多的工作项 - 您可能有100万个要处理的项目,但您的系统只有8个内核。在这种情况下,使用固定数量的线程,并使每个线程处理多个工作项,效率要高得多。通过将"任务"与"线程"分开,您正在打破工作==线程的耦合。

总的来说,我建议使用Task而不是创建自己的线程。这是一种更好、更强大、更灵活的开发模式,特别是它允许您以非常清晰的方式处理异常,生成诸如连续性之类的好东西等等。


6

以下是一些区别:

  • Task 默认情况下 使用线程池,而直接使用Thread将需要创建新线程。
  • Task 将处理异常和结果,因此使用更加容易。
  • Task 可以支持取消操作,而使用线程,则需要自己实现。

任务不一定使用线程池。这是默认设置(在.NET 4中),但并非总是如此。 - Reed Copsey
1
@Reed 谢谢。有哪些异常?如何覆盖?您介意给我指一下参考资料吗? - Aliostad
2
由TaskScheduler决定任务在何处以及如何运行。默认的调度程序使用线程池(除非设置了LongRunning提示,此时任务将获得专用线程),但是调度程序可以执行任何操作。此外,连续性通常会使用基于当前SynchronizationContext的调度程序运行。我在这里写过关于调度的内容:http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/ - Reed Copsey
1
太棒了!!填补了我在线程知识方面的重要空白。非常感谢。 - Aliostad

5

一个任务指的是您想要执行的操作或工作。

线程可能是执行该工作的执行者或工作者之一。


4
根据MSDN参考文档:
任务并行库(TPL)是.NET Framework 4中System.Threading和System.Threading.Tasks名称空间中的一组公共类型和API。TPL的目的是简化将并行性和并发性添加到应用程序的过程,从而使开发人员更加高效。TPL动态地缩放并发的程度以最大限度地利用所有可用的处理器。此外,TPL处理工作的分区、线程池上的线程调度、取消支持、状态管理和其他低级细节。通过使用TPL,您可以在专注于程序设计的工作的同时最大限度地提高代码的性能。
因此,似乎Task是编写异步操作的首选方法,因为大部分工作都由框架处理。但另一方面,Thread仍然适用于现有代码和需要显式分配和管理操作系统线程的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接