-1

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

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

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

4

4 回答 4

2

为什么不使用响应式扩展框架?它应该是你所描述的想法,它提供了很大的灵活性。这是管理多个订阅的方法

于 2013-05-22T21:08:23.843 回答
0

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

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

于 2013-05-22T21:01:50.933 回答
0

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

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

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

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

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

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

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

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

而已。当没有更多数据时消费者会自动阻塞在循环中,当没有更多数据并且生产者调用时foreach他们会自动退出。foreachCompleteAdding()

于 2013-05-22T21:02:53.053 回答
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(); });
        }
    }
}
于 2013-05-22T21:03:14.730 回答