我有一个C# 4应用程序,它订阅了一个事件,我希望该事件会被快速连续引发很多次。每次它被抛出时,都需要做一些我不想阻塞事件线程的工作。
我感觉我应该把这个“块”工作传递给后台线程/任务,并允许事件线程继续,但是我也需要确保不会创建太多的线程,因为正如我所说的,我希望这个事件会被快速引发很多次。
有没有一种公认的模式或推荐的方法来将事件处理程序工作负载传递给后台线程,但限制创建的线程数量?
我觉得应该有一些方法来使用任务并行库来实现这一点,但我找不到任何东西来做我目前需要的事情。
如果有人需要更多的信息,请让我知道,因为我很欣赏我所说的话。
谢谢。
发布于 2012-07-20 18:50:30
如果您希望在每次引发事件时执行的“少量工作”很小,并且主要受CPU限制,那么每次只需启动一个Task
。ThreadPool
将确定要使用的最优线程数,它很可能接近您拥有的CPU核心数。在这种情况下,您不必担心限制并行度。
如果每次提升的工作可能需要很长时间,或者它主要是IO绑定的,那么您应该手动限制并行度。要做到这一点,一种方法是让少量的线程在没有工作的情况下阻塞,否则处理队列中的事件。您可以通过使用BlockingCollection
来实现这一点。
如果您可以使用TPL 4.5,那么最好的选择可能是使用.Net数据流中的ActionBlock
,并设置MaximumDegreeOfParallelism
。有了它,当没有工作时,您不会浪费任何线程,并且您可以设置要使用(或不使用)的最大线程数。
发布于 2012-07-20 16:20:40
在应用程序运行期间,不要创建任何线程。在事件触发时创建(或出池)任务,并将它们提交/排队到线程池。
如果您没有实际创建任何线程(除了在启动时为线程池提供服务的线程),您就不能创建太多的线程!
您可以创建太多的任务,但有其他机制可以限制这一点(我通常也会在启动时创建固定数量的任务,但比线程的数量多得多,并将它们汇集到一个BlockingCollection中,在运行期间弹出/加载/提交/puishingBack,以便提供数据/任务流控制)。
发布于 2012-07-22 00:03:42
ActionBlock和第三方物流的其余部分也可以在.NET 4中以CTP的形式提供--对于主要场景来说,它是可靠的(我在一个大型项目中使用CTP没有任何问题-当然,您的里程可能会有所不同)
如果您在调用远程web服务后还有其他工作需要完成,数据流模块甚至允许您创建管道(例如:整理结果、更新日志)
https://stackoverflow.com/questions/11575413
复制相似问题