1

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

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

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

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

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

谢谢。

4

3 回答 3

1

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

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

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

于 2012-07-20T08:20:40.097 回答
1

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

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

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

于 2012-07-20T10:50:29.637 回答
0

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

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

于 2012-07-21T16:03:41.790 回答