【发布时间】:2010-10-02 15:15:32
【问题描述】:
我在几个程序中使用了多个线程,但还是觉得不太舒服。
目前有哪些适用于 C#/.NET 的多线程库,其中一个有哪些优势?
我所说的多线程库是指所有有助于使多线程编程更容易的东西。
您定期使用什么 .NET 集成(即像 ThreadPool)? 您遇到了哪些问题?
【问题讨论】:
标签: c# .net multithreading
我在几个程序中使用了多个线程,但还是觉得不太舒服。
目前有哪些适用于 C#/.NET 的多线程库,其中一个有哪些优势?
我所说的多线程库是指所有有助于使多线程编程更容易的东西。
您定期使用什么 .NET 集成(即像 ThreadPool)? 您遇到了哪些问题?
【问题讨论】:
标签: c# .net multithreading
我写了很多线程代码,甚至实现了我自己的线程池和调度程序。很多都记录在这里:
http://web.archive.org/web/20120708232527/http://devplanet.com/blogs/brianr/default.aspx
只要意识到我写这些是为了非常特定的目的并在这些条件下测试它们,并没有真正的灵丹妙药。
【讨论】:
查看Power Threading 库。
【讨论】:
您可能想查看有关线程模式的系列文章。现在它有实现 WorkerThread 和 ThreadedQueue 的示例代码。
http://devpinoy.org/blogs/jakelite/archive/tags/Threading+Patterns/default.aspx
【讨论】:
【讨论】:
你应该看看Concurrency & Coordination Runtime。 CCR 一开始可能有点令人生畏,因为它需要稍微不同的思维定势。这个video 很好地解释了它的工作原理......
在我看来,这将是可行的方法,而且我还听说它将使用与 TPL 相同的调度程序。
【讨论】:
您不必显式使用线程池,如果您需要异步调用,可以使用 BeginInvoke-EndInvoke。它在幕后使用线程池。见这里:http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx
【讨论】:
请记住,当您不再需要线程时,您确实应该关闭线程(或允许线程池释放),除非您很快会再次需要它们。我这么说的原因是每个线程都需要堆栈内存(通常是 1mb),所以当你有应用程序坐在线程上但不使用它们时,你就是在浪费内存。
例如,我机器上的 Outlook 现在有 20 个线程打开并且使用 0% 的 CPU。这只是浪费(至少)20mb 内存。 Word 还使用另外 10 个 CPU 为 0% 的线程。 30mb 可能看起来不多,但如果每个应用程序都浪费 10-20 个线程怎么办?
同样,如果您需要定期访问线程池,则无需关闭它(创建/销毁线程有开销)。
【讨论】:
在应用程序中使用多线程有多种原因:
一个人应该选择的方法取决于你想要做什么。例如,对于 UI 响应性,请考虑使用 BackgroundWorker。
对于并发操作(例如服务器:某些东西必须是并行的,但即使在单核系统上也可能需要并发),考虑使用线程池或,如果任务是长期存在的并且您需要很多任务,请考虑为每个任务使用一个线程。
如果您有一个所谓的令人尴尬的并行问题,可以很容易地分解成小的子问题,请考虑使用从队列中提取任务的工作线程池(与 CPU 内核一样多的线程)。 Microsoft Task Parallel Library (TPL) 可能会有所帮助。如果可以轻松地将作业表示为单子流计算(即在 LINQ 中使用转换和聚合等工作的查询),则在 TPL 之上运行的并行 LINQ(相同链接)可能会有所帮助。
还有其他方法,例如在 Erlang 中看到的Actor-style parallelism,由于缺乏绿色线程模型或实现相同的方法(例如 CLR 支持的延续),因此在 .NET 中更难有效实现。
【讨论】:
对我来说,框架的内置类绰绰有余。 Threadpool 既古怪又蹩脚,但您可以轻松编写自己的代码。
我经常将BackgroundWorker 类用于前端,因为它使生活变得更加轻松 - 事件处理程序的调用是自动完成的。
我会定期手动启动线程并将它们保存在带有ManualResetEvent 的字典中,以便能够检查其中谁已经结束。我为此使用WaitHandle.WaitAll() 方法。问题是,WaitHandle.WaitAll 一次不接受超过 64 个 WaitHandle 的数组。
【讨论】:
我的建议是在迁移到任何其他库之前先熟悉线程池。很多框架代码都使用线程池,所以即使你碰巧找到了 The Best Threads Library(TM),你仍然需要使用线程池,所以你真的需要了解这一点。
您还应该记住,在实现线程池和对其进行调整方面已经投入了大量工作。即将发布的 .NET 版本通过并行库的开发引发了许多改进。
在我看来,当前线程池的许多“问题”都可以通过了解其优缺点来解决。
【讨论】: