制作并发程序的不同方式的差异

时间:2010-04-30 10:40:43

标签: c# .net-4.0

有什么区别:

  1. 开始新主题
  2. 使用TPL
  3. 使用BackgroundWorker
  4. 所有这些都创造了并发性,但这些之间的低级别差异是什么?无论如何都要做3个线程吗?

    由于

3 个答案:

答案 0 :(得分:19)

它们都在内部使用线程,不同之处在于每个API的抽象级别以及线程的使用方式。让我们重新排序你的列表并查看从最低到最高抽象级别的三种技术:

  1. 手动启动新帖子

    这实际上在操作系统中创建了一个新线程。您的代码将在该线程上执行。

  2. 使用BackgroundWorker

    在内部,它使用了一种叫做.net ThreadPool的东西。线程池基本上是一个可用线程池。您的代码被分配到其中一个可用线程上并在该线程上运行。

    池管理可用线程的数量,并在内部根据需要在某些边界内创建和销毁线程。这很有用,因为池可以有一些算法来优化线程创建。线程创建是一个非常昂贵的过程,因此如果合适,线程池会保持线程活动并将其重用于将来的请求。您可以通过指定最小/最大线程数以及类似的一些小调整来对池进行一些有限的控制。

    还有其他直接使用ThreadPool的方法,例如QueueUserWorkItem(...)

  3. 使用任务并行库

    这是一个更高的抽象。您创建“任务”并告诉TPL执行它们。 TPL隐藏了所有关于确切使用多少线程和优先级的问题等.TPL能够根据特定的机器性能和可用的CPU资源重用线程并对其进行管理。

    例如,给定100个任务,在四核上,TPL可能会产生4个线程,但在8核上它可能产生8并在每个任务完成时将任务分配到可用线程上。

  4. 所以回答你的问题。所有3种技术都使用线程,但随着每个级别的上升,对这些线程的控制和感知量会降低。

    在大多数情况下,我建议您使用TPL。除非您需要对线程数量及其创建/销毁进行特定的非常精确的控制,否则TPL将非常适合您。

答案 1 :(得分:3)

  1. 启动新主题是三者中最昂贵的,但您获得的可能性最大。就像设置公寓模型和优先级一样。

  2. 任务并行库将在ThreadPool上运行任务(除非将Task标记为需要自己的Thread)并添加异常处理和等待完成功能。

  3. BackgroundWorker 仅对运行从WinForms或WPF生成的任务有用。它还使用Threadpool

  4. 额外: ThreadPool 。用于运行简短的任务,而无需创建单独的线程的开销。

答案 2 :(得分:2)

创建一个线程只是......你产生一个线程并同时运行到你的主进程线程。

在TPL中,如果您创建一个Task,它将使用一个线程池来查找运行该任务的空闲线程。当你创建大量任务时,这可以更有效,因为TPL能够平衡任意数量的空闲线程的负载(可能是根据你拥有的核心数来平衡线程数#,但我肯定不知道这一点。 )

最后,BackgroundWorker在单独的线程上运行您的工作。它实际上只是一个很好的抽象,可以让你从线程的混乱部分中解脱出来,因​​为它是为你管理的。如果我没有弄错的话,它还提供了一种发送状态更新的方法。 (不确定这是否使用Windows线程池,但我不会感到惊讶)

最后,您必须选择适合您的程序的内容,但TPL任务的目的是允许您有效地安排可以并行运行的任务,而创建线程或使用后台工作程序可能会更好运行操作或你希望后台线程永远等待某些信号的场景(如果你只是等待一些事件发出信号,我实际上建议使用RegisteredWait。)