5

我想知道对于需要大量性能的任务使用什么。 Backgroundworker,ThreadThreadPool?

到目前为止,我一直在使用 Threads,但我需要提高应用程序的速度。

4

3 回答 3

13

BackgroundWorker 与线程池线程是一回事。它增加了在 UI 线程上运行事件的能力。对于显示进度和使用结果更新 UI 非常有用。因此,它的典型用法是防止 UI 在需要完成工作时冻结。性能不是首要目标,异步运行代码才是。在以后的 .NET 版本中,Task<> 类和 async/await 关键字也巧妙地扩展了这种模式。

线程池线程对于避免消耗资源很有用。线程是一个昂贵的操作系统对象,您可以创建的数量非常有限。一个线程需要 5 个操作系统句柄和 1 兆字节的虚拟内存地址空间。没有 Dispose() 方法可以提前释放这些句柄。线程池的存在主要是为了重用线程并确保没有太多线程处于活动状态。重要的是,仅当它所做的工作受到限制时才使用线程池线程,理想情况下不超过半秒。并且不经常阻塞。因此,它最适合短时间的工作,而不是性能重要的任何事情。处理 I/O 完成是 TP 线程的理想任务。

是的,也可以使用线程来提高程序的性能。您可以通过使用 Thread 或使用 TaskContinuationOptions.LongRunning 的 Task<> 来实现。实际获得性能改进有一些硬性要求,它们非常严格:

  • 您需要多个线程。在理想情况下,两个线程可以将完成工作所需的时间减半。更少,您使用的线程越多。接近这个理想是多么困难,它不会无限扩展。谷歌“阿姆达尔定律”获取信息。
  • 您需要一台具有多核处理器的机器。这几天很容易得到。您创建的线程数不应超过可用内核数。使用更多通常会降低性能。
  • 您需要那种受计算约束的作业,让处理器的执行引擎成为受限资源。这很常见,但肯定不是灌篮高手。许多作业实际上受到 I/O 吞吐量的限制,例如从文件读取或 dbase 查询。或者受到处理器从 RAM 读取数据的速率的限制。此类作业不会从线程中受益,您将拥有多个可用的执行引擎,但您仍然只有一个磁盘和一个内存总线。
  • 您需要一种算法,该算法可以跨多个线程分配工作,而几乎不需要同步。这通常是要解决的棘手问题,许多算法本质上是非常顺序的,不容易并行化。
  • 您需要时间和耐心才能使代码稳定并运行良好。编写线程代码是很困难的,而线程竞赛会使您的程序每月崩溃一次,或者偶尔会产生无效的结果,这可能是一个主要的时间消耗。
于 2013-06-09T13:16:46.043 回答
1

在线程中启动 CPU 密集型任务的框架与您的问题无关,除非您有过于细粒度的子任务。

当您有多个 CPU 时,您需要将您的工作拆分为可以并行执行的子任务。

于 2013-06-09T10:16:00.757 回答
0

这个选择其实并不重要。BackgroundWorker 是一个 ThreadPool 线程,所以无论如何这没有区别。但是,您可以尝试使用 ThreadPool.SetMaxThreads 优化线程数。

您可能希望使用有助于优化并行执行的 System.Threading.Task 类。

于 2013-06-09T10:16:59.780 回答