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