【发布时间】:2017-10-11 15:04:58
【问题描述】:
我正在编写一个从数千个客户端获取数据的服务器。我想并行处理这些数据,但是每个客户端的数据必须按顺序依次处理。
例如,如果我有客户端 A、B 和 C,我将同时处理来自所有 3 个客户端的数据,但每次只处理来自每个客户端的单个项目。
我的第一次尝试是创建一种分区队列,每个分区都有一个Task 消费:ConcurrentDictionary<string, BlockingCollection<T>>,其中string 是客户端标识符。有了这个,我创建了一个Task 来从每个客户端消费,并将它们保存在字典ConcurrentDictionary<string, Task> 中。任务很简单,使用GetConsumingEnumerable:
return Task.Run(() =>
{
foreach (var item in list.GetConsumingEnumerable())
{
this.action(item);
}
});
这很有效,但最多只有大约 75 个客户端 - 此后,每秒项目数的性能迅速下降,可能是由于任务之间的争用。
有没有更好的方法来做到这一点?也许使用较小的固定数量的消费线程,可以以某种方式轮换它们从哪个分区消费?
我在 .NET Framework 本身中没有发现任何有用的东西,但我觉得有可能以某种方式利用 TPL?
编辑 我不只是询问如何处理具有多个生产者和单个消费者的单个队列。另外,我只对基于 TPL 的解决方案感兴趣。我只是认为它可能会有所帮助。
【问题讨论】:
-
@GregoryNeal 不,这比我的问题简单得多;事实上,我在我的问题中举了一个单一消费者的例子!能否请您删除此标记,以免我的问题被未阅读该问题的其他人忽略或标记为欺骗?
-
@Cocowalla - 如果您指出这些是连接的客户端还是断开的客户端(厚客户端与瘦客户端),这可能会有所帮助。每个人的解决方案可能会采用截然不同的方法。
-
@NightOwl888 实际上,客户端正在向消息代理发送消息,而服务器正在使用它们。因此,在服务器上运行的消息代理客户端正在将传入消息添加到我要并行处理的队列中。
-
假设队列中的下一个项目是给客户端 A 的,但是客户端 A 已经有另一个项目正在被一个消费者处理。其他消费者应该等待该项目完成还是允许他们跳过该项目并获取下一个项目(对于另一个客户)?
-
@Evk 他们可以跳过它并获取另一个;要求是我们一次只为任何给定的客户端处理一条消息 - 但我们希望同时处理多条消息(针对不同的客户端)
标签: c# .net queue task-parallel-library