单个生产者多个消费者的架构

时间:2013-05-22 20:56:40

标签: c# c#-4.0 architecture

我正在设计用于显示市场数据的GUI。目前,我有多个窗口使用相同的数据,但显示它的不同方面。我试图找出构建这个系统的最佳方法。

我有一个市场数据生产者和多个消费者,他们向生产者注册回调。当生产者准备好数据时,它会遍历消费者列表并通过回调将数据分发给每个消费者。我不确定这是否是分发数据的最佳方法。每个消费者必须等待前一个消费者完成处理回调才能获得其数据。

有没有一种方法可以让所有消费者同时获得数据或延迟最少?我正在使用C#4.0,并想知道是否有任何语言功能可以实现这一点。

4 个答案:

答案 0 :(得分:2)

为什么不使用Reactive Extensions Framework?它应该是你所描述的想法,它提供了很大的灵活性。以下是管理multiple subscriptions

的方法

答案 1 :(得分:0)

对于这种情况,您应该使用诸如RabbitMQ或MSMQ之类的队列。它们是此类发布者/订阅者操作​​的最佳选择。

如果这不是一个选项,你可以使用线程触发回调或将它们设置为WCF激活和忘记呼叫(OneWay)。

答案 2 :(得分:0)

您可以通过为每个消费者使用单独的BlockingCollection来寻求一个相当简单的解决方案。

生产者线程只需要它自己管理的List<>BlockingCollection队列。当生产者线程生成一个项目时,只需要使用BlockingCollection.Add()将其添加到列表中的每个队列。注意:这是多次排队的相同项 - 一次到每个消费者队列。

项类型应该是不可变的引用类型 - 然后在消费者之间共享是安全的,而开销只是每个消费者队列中的引用。

这不是最有效的路线,因为它需要每个消费者一个队列,但我认为除非队列很大,否则它太糟糕了。这很容易理解和实现。

当没有更多数据时,BlockingCollection可以很容易地告诉消费者线程,以便它们可以干净地退出。

生产者线程调用BlockingCollection.CompleteAdding()向消费线程发出信号,表示当没有更多数据时它们应该退出。

同时,所有消费线程需要这样做(假设queue是他们的BlockingCollection队列):

foreach (var item in queue.GetConsumingEnumerable())
{
    ... process item
}

就是这样。当没有更多数据时,消费者将自动在foreach循环中阻止,当没有更多数据时,他们将自动退出foreach 生产者已调用{ {1}}。

答案 3 :(得分:0)

如果每个注册的回调都是从他们自己的线程(很可能是一个线程池线程)调用的,这很容易做到:

public class Foo
{
    private HashSet<Action> callbacks = new HashSet<Action>();
    public event Action MyEvent
    {
        add
        {
            callbacks.Add(value);
        }
        remove
        {
            callbacks.Remove(value);
        }
    }

    private void FireMyEvent()
    {
        foreach (var action in callbacks)
        {
            ThreadPool.QueueUserWorkItem(o => { action(); });
        }
    }
}
相关问题