Task(System.Threading.Task)和Thread之间的区别

根据我的理解,Task和Thread之间的区别是任务发生在线程池中,而线程是我需要自己管理的东西..(并且该任务可以取消并返回到线程池中他的任务结束)

但在一些博客中,我读到如果操作系统需要创建任务并创建thread =>,那么创建(和销毁)任务将更容易。

有人可以解释为什么创建任务很简单那个线程?

(或许我在这里遗漏了一些东西……)

当你说Task是一个System.Threading.Task时,我你正在谈论的是什么。 如果是这种情况,那么你可以这样思考:

  • 程序可以有许multithreading,但处理器核心一次只能运行一个线程。
    • 线程非常昂贵,并且在运行的线程之间切换也非常昂贵。
    • 所以…有数千个线程做东西是低效的。 想象一下,如果你的老师给做了10,000个任务。 你花了很多时间在他们之间骑车,你永远不会做任何事情。 如果你开始太multithreading,CPU也会发生同样的事情。

为了解决这个问题,.NET框架允许您创建任务。 任务是捆绑到对象中的一些工作,它们允许您执行有趣的操作,例如捕获工作的输出和连接工作( 首先去商店, 然后购买杂志)。

任务安排在线程池上。 具体的线程数取决于所使用的调度程序,但默认调度程序会尝试选择一些线程,这些线程最适合您拥有的CPU核心数以及任务实际使用CPU时间所花费的时间。 如果您愿意,您甚至可以编写自己的调度程序来执行特定操作,例如确保该调度程序的所有任务始终在单个线程上运行。

因此,将“任务”视为待办事项列表中的项目。 你可能一次可以做5件事,但是如果你的老板给你10000,他们会在你的收件箱堆积,直到你做的前5个完成。 任务和ThreadPool之间的区别在于,任务(如前所述)可以让您更好地控制不同工作项之间的关系(想象多个指令拼接在一起的待办事项),而ThreadPool只允许您排队一堆单独的单项目(function)。

您正在听到两种不同的任务概念。 第一个是工作的概念,第二个是工艺的概念。

很久以前(用计算机术语),没有线程。 程序的每个运行实例都被称为进程,因为它只是一步一步地执行,直到它退出。 这将过程的直观概念与工厂assembly线的一系列步骤相匹配。 操作系统管理进程抽象。

然后,开发人员开始向工厂添加多条assembly线。 现在一个程序可以同时执行多个操作,并且库或(更常见的是今天)操作系统将管理每个线程内的步骤的调度。 线程是一种轻量级进程,但线程属于进程,进程中的所有线程共享内存。 另一方面,多个进程不能混淆彼此的记忆。 因此,Web服务器中的多个线程都可以访问有关连接的相同信息,但Word无法访问Excel的内存数据结构,因为Word和Excel作为单独的进程运行。 将进程作为一系列步骤的想法与具有线程的进程模型并不真正匹配,因此有些人将“抽象以前称为进程”称为任务。 这是您在博客文章中看到的第二个任务定义。 请注意,很多人仍然使用“进程”这个词来表示这一点。

好吧,随着线程变得越来越普遍,开发人员在它们之上添加了更多的抽象,以使它们更易于使用。 这导致了线程池的兴起,这是一个由库管理的线程池“池”。 您将库传递给作业,并且库选择一个线程并在该线程上运行作业。 .NET框架有一个线程池实现,当你第一次听说“任务”时,文档真正意味着你传递给线程池的工作。

所以从某种意义上说,文档和博客文章都是正确的。 任务一词的超载是令人遗憾的混乱之源。

线程已经成为.Net的一部分v1.0,任务在.Net 4.0中发布的任务并行库TPL中引入。

您可以将Task视为Thread的更复杂版本。 它们非常易于使用,并且具有很多优于Threads的优点,如下所示:

  1. 您可以为任务创建返回类型,就像它们是函数一样。
  2. 您可以使用“ContinueWith”方法,它将等待上一个任务然后开始执行。 (抽象等待)
  3. 摘要根据我公司的指导应该避免使用锁。
  4. 您可以使用Task.WaitAll并传递一系列任务,这样您就可以等到所有任务完成。
  5. 您可以将任务附加到父任务,因此您可以决定父项或子项是否将首先存在。
  6. 您可以使用LINQ查询实现数据并行。
  7. 您可以创建并行for和foreach循环
  8. 使用任务很容易处理exception。
  9. *最重要的是,如果在单核计算机上运行相同的代码,它将只作为单个进程运行,而不会产生任何线程开销。

线程上任务的缺点:

  1. 你需要.Net 4.0
  2. 学习过操作系统的新手可以更好地理解线程。
  3. 框架的新function,因此没有太多的帮助。

一些提示: – 始终使用语义完美和标准的Task.Factory.StartNew方法。

有关更多信息,请查看Task Parallel Libray http://msdn.microsoft.com/en-us/library/dd460717.aspx

扩展Eric Lippert的评论:

Thread是一种允许应用程序并行执行多项操作的方法。 例如,您的应用程序可能有一个线程处理来自用户的事件,如按钮单击,以及另一个执行长计算的线程。 这样,你可以“同时”做两件事。 如果您不这样做,用户将不会在计算完成之前单击按钮。 因此, Thread可以执行您编写的一些代码。

另一方面, Task代表了某种工作的抽象概念。 该作业可以有结果,您可以等到作业完成(通过调用Wait() )或者说您想在作业完成后执行某些操作(通过调用ContinueWith() )。

您想要表示的最常见的工作是与当前代码并行执行某些计算。 而Task为您提供了一种简单的方法。 代码实际运行的方式和时间由TaskScheduler定义。 默认的一个使用ThreadPool :一组可以运行任何代码的线程。 这样做是因为创建和切换低效的线程。

但是Task不必与某些代码直接关联。 您可以使用TaskCompletionSource创建Task ,然后随时设置其结果。 例如,您可以创建一个Task并在用户单击按钮时将其标记为已完成。 其他一些代码可以等待该Task并且在等待时,没有代码执行该Task

如果您想知道何时使用Task以及何时使用ThreadTask更易于使用,并且更有效地创建您自己的Thread 。 但有时候,你需要比Task提供的控制更多的控制权。 在这些情况下,直接使用Thread有意义的。

任务实际上只是手动旋转线程的样板代码的包装器。 从根本上说,没有区别。 任务只是使线程管理更容易,并且由于样板噪声的减少,它们通常更具表现力。