【问题标题】:Multi-threading libraries for .NET.NET 的多线程库
【发布时间】:2010-10-02 15:15:32
【问题描述】:

我在几个程序中使用了多个线程,但还是觉得不太舒服。

目前有哪些适用于 C#/.NET 的多线程库,其中一个有哪些优势?

我所说的多线程库是指所有有助于使多线程编程更容易的东西。

您定期使用什么 .NET 集成(即像 ThreadPool)? 您遇到了哪些问题?

【问题讨论】:

    标签: c# .net multithreading


    【解决方案1】:

    我写了很多线程代码,甚至实现了我自己的线程池和调度程序。很多都记录在这里:

    http://web.archive.org/web/20120708232527/http://devplanet.com/blogs/brianr/default.aspx

    只要意识到我写这些是为了非常特定的目的并在这些条件下测试它们,并没有真正的灵丹妙药。

    【讨论】:

      【解决方案2】:

      查看Power Threading 库。

      【讨论】:

      • 强大的线程库非常酷,但我不会在生产代码中使用它的一些功能,因为它利用了一些编译器模式,这些模式不能保证在未来的 .网
      【解决方案3】:

      您可能想查看有关线程模式的系列文章。现在它有实现 WorkerThread 和 ThreadedQueue 的示例代码。

      http://devpinoy.org/blogs/jakelite/archive/tags/Threading+Patterns/default.aspx

      【讨论】:

        【解决方案4】:

        【讨论】:

          【解决方案5】:

          你应该看看Concurrency & Coordination Runtime。 CCR 一开始可能有点令人生畏,因为它需要稍微不同的思维定势。这个video 很好地解释了它的工作原理......

          在我看来,这将是可行的方法,而且我还听说它将使用与 TPL 相同的调度程序。

          【讨论】:

            【解决方案6】:

            您不必显式使用线程池,如果您需要异步调用,可以使用 BeginInvoke-EndInvoke。它在幕后使用线程池。见这里:http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

            【讨论】:

              【解决方案7】:

              请记住,当您不再需要线程时,您确实应该关闭线程(或允许线程池释放),除非您很快会再次需要它们。我这么说的原因是每个线程都需要堆栈内存(通常是 1mb),所以当你有应用程序坐在线程上但不使用它们时,你就是在浪费内存。

              例如,我机器上的 Outlook 现在有 20 个线程打开并且使用 0% 的 CPU。这只是浪费(至少)20mb 内存。 Word 还使用另外 10 个 CPU 为 0% 的线程。 30mb 可能看起来不多,但如果每个应用程序都浪费 10-20 个线程怎么办?

              同样,如果您需要定期访问线程池,则无需关闭它(创建/销毁线程有开销)。

              【讨论】:

              • 不浪费内存 - 浪费虚拟地址空间。 Windows 上的大多数语言在创建线程时会保留 1MB 的堆栈空间,是的,但它是使用特殊页面保护(保护页面)按需提交的。
              • 内存在需要时才提交,是的,但在不再需要时是否已清理?我的问题不在于创建线程而不是使用它们,而是将它们用于短期任务,而不是在不再需要它们时处理它们。
              【解决方案8】:

              在应用程序中使用多线程有多种原因:

              • UI 响应性
              • 并发操作
              • 并行加速

              一个人应该选择的方法取决于你想要做什么。例如,对于 UI 响应性,请考虑使用 BackgroundWorker

              对于并发操作(例如服务器:某些东西必须是并行的,但即使在单核系统上也可能需要并发),考虑使用线程池或,如果任务是长期存在的并且您需要很多任务,请考虑为每个任务使用一个线程。

              如果您有一个所谓的令人尴尬的并行问题,可以很容易地分解成小的子问题,请考虑使用从队列中提取任务的工作线程池(与 CPU 内核一样多的线程)。 Microsoft Task Parallel Library (TPL) 可能会有所帮助。如果可以轻松地将作业表示为单子流计算(即在 LINQ 中使用转换和聚合等工作的查询),则在 TPL 之上运行的并行 LINQ(相同链接)可能会有所帮助。

              还有其他方法,例如在 Erlang 中看到的Actor-style parallelism,由于缺乏绿色线程模型或实现相同的方法(例如 CLR 支持的延续),因此在 .NET 中更难有效实现。

              【讨论】:

              • 我过去曾成功使用过 TPL ——而且它很容易上手,就线程而言。
              【解决方案9】:

              对我来说,框架的内置类绰绰有余。 Threadpool 既古怪又蹩脚,但您可以轻松编写自己的代码。

              我经常将BackgroundWorker 类用于前端,因为它使生活变得更加轻松 - 事件处理程序的调用是自动完成的。

              我会定期手动启动线程并将它们保存在带有ManualResetEvent 的字典中,以便能够检查其中谁已经结束。我为此使用WaitHandle.WaitAll() 方法。问题是,WaitHandle.WaitAll 一次不接受超过 64 个 WaitHandle 的数组。

              【讨论】:

                【解决方案10】:

                我的建议是在迁移到任何其他库之前先熟悉线程池。很多框架代码都使用线程池,所以即使你碰巧找到了 The Best Threads Library(TM),你仍然需要使用线程池,所以你真的需要了解这一点。

                您还应该记住,在实现线程池和对其进行调整方面已经投入了大量工作。即将发布的 .NET 版本通过并行库的开发引发了许多改进。

                在我看来,当前线程池的许多“问题”都可以通过了解其优缺点来解决。

                【讨论】:

                • "...了解它的优点和缺点。"如问题中所问,您遇到了哪些问题。我仍然相信一个人不必犯错误才能学习,我也尝试从别人的错误中学习。
                猜你喜欢
                • 2011-08-13
                • 1970-01-01
                • 2011-06-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-01-15
                • 1970-01-01
                • 2013-11-14
                相关资源
                最近更新 更多