【问题标题】:Handling workload of raised events in background threads in C# 4 and controlling the number of threads在 C# 4 中处理后台线程中引发事件的工作负载并控制线程数
【发布时间】:2012-07-20 08:12:35
【问题描述】:

我有一个 C# 4 应用程序正在订阅一个事件,我希望该事件会快速连续地引发很多次。每次引发它时都需要做一些我不想阻塞事件线程的工作。

感觉就像我应该将这个“块”工作传递给后台线程/任务并允许事件线程继续,但是我还需要确保没有创建太多线程,正如我所说, 我希望这个事件能很快被提出很多次。

是否有公认的模式或推荐的方法将事件处理程序工作负载传递给后台线程但限制创建的线程数量?

感觉应该有某种方法可以为此使用任务并行库,但目前找不到完全符合我需要的任何东西。

如果有人需要更多信息,请告诉我,因为我很感激我对我所说的内容非常笼统。

谢谢。

【问题讨论】:

    标签: multithreading c#-4.0 event-handling backgroundworker task-parallel-library


    【解决方案1】:

    如果您希望在每次引发事件时执行的“工作量”很小并且主要受 CPU 限制,那么每次只需启动 TaskThreadPool 将确定要使用的最佳线程数,这很可能接近您拥有的 CPU 内核数。在这种情况下,您不必担心限制并行度。

    如果每次提升的工作可能需要很长时间,或者如果它主要受 IO 限制,那么您应该手动限制并行度。一种方法是让少量线程在没有工作时阻塞,否则处理队列中的事件。您可以使用BlockingCollection 来实现这一点。

    如果可以使用 .Net 4.5,最好的选择可能是使用 TPL Dataflow 中的 ActionBlock 并设置 MaximumDegreeOfParallelism。有了它,你不会在没有工作的时候浪费任何线程,并且可以设置使用(或不使用)的最大线程数。

    【讨论】:

    • 是的,这项工作主要受 IO 限制,它依赖于对远程 Web 服务的调用并等待响应。不幸的是,我无法访问 .NET 4.5,但 ActionBlock 听起来确实像我所追求的!
    【解决方案2】:

    在应用运行期间不要创建任何线程。在事件触发时创建(或分离)任务并将它们提交/排队到线程池。

    如果你不实际创建任何线程,(除了在启动时为线程池服务的线程),你不能创建太多线程!

    你可以创建太多的任务,但还有其他机制可以限制这一点,(我通常在启动时创建固定数量的任务,但比线程数多得多,并将它们汇集在 BlockingCollection 中,弹出/loading/submitting/puishingBack 在运行期间提供数据/任务流控制)。

    【讨论】:

    • 谢谢,我很欣赏使用任务 API 比创建自己的线程更好,但我真的在寻找一个示例,说明如何控制/限制任务的创建/分配作为事件被触发,并且是确定此限制的合理方法。
    • 您的任务有多大(空间方面)?如果它们包含 10MB 的网络数据缓冲区,则无法创建这么多:)。我经常只是用湿手指选择一个数字,例如 256:) 在运行时使对象池深度可配置和/或可更改以进行优化非常容易 - 如果请求的池深度小于实际池深度,循环创建更多任务。如果请求的池深度小于实际池深度,则停止重新池化返回的任务,直到请求=实际,以便多余的任务得到 GC。
    • 您究竟是如何汇集Tasks 的?我认为这是不可能的,因为一旦Task 完成,您就无法重新启动它。
    • 一旦线程终止,您将无法重新启动它。任务对象只是一个对象——你可以用它做你想做的事——将它的最后一个 ref 清空以确保它得到 GC 或将它推回 BlockingCollection 以供重用。
    • 是的,但它是一个具有特定语义的对象。这种语义表明,一旦你设置了它的结果,你就不能“取消设置”它。正因为如此,重用Task 你描述的方式是不可能的。 (您可以将一个新的Task 推送到集合中,但这不会成为池,也没有用。)
    【解决方案3】:

    ActionBlock 和 TPL 数据流的其余部分也可用于 .NET 4,以 CTP 的形式 - 对于主要场景,它是可靠的(我在大型项目中使用 CTP 没有任何问题 - 当然你的里程可能不同)

    如果您在调用远程 Web 服务后还有其他工作需要完成(例如:结果整理、更新日志),数据流块甚至允许您创建管道

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-25
      相关资源
      最近更新 更多