设计许多生产者一个消费者双向沟通

时间:2012-11-21 08:31:57

标签: c# producer-consumer

我正在写交易软件。我的系统生成需要处理的“顺序项”(1,2,3 ...)(在我的应用程序中,每个项目都是执行顺序,id是所谓的内部订单ID)。

我有许多线程可以生成项目(许多策略),但保证每个项目都会生成完全一次。

我只有一个应该

的处理器(订单执行者)
  • 每当有新项目可用时,请提交执行(下订单)
  • 在回调中接收结果并将其更新为“项目结果”(从证券交易所获得回复)

每个制作人都应该

  • 提交执行项目的“亮片包”(例如提交“1234,1235,1236,1237”)
  • 阻止,直到所有项目的结果都可用。当所有项目的结果都可用时 - 进程

请注意:

  • 项目可以从不同的线程并行提交
  • 我需要最小的延迟和最小的“锁定”
  • 很高兴有一个易于移植到c ++的代码
  • 在任何时候我都有相当“有限”的“现场”身份证。例如,我不能同时拥有id的“1和10000”。因为每当创建新的id时 - 必须对其进行处理和清理。所以我总是将id设置为彼此接近(例如~9900-10000)。因此,使用循环数组实现
  • 可能是有意义的

如果你能提出建议 - 请提出建议。我在下面添加了我的奇怪实现,但没有必要阅读它。


这是我的 prolem 实施:

    private Dictionary<uint, AutoResetEvent> transactionsEvents = new Dictionary<uint, AutoResetEvent>();
    private Dictionary<uint, TransactionResult> transactionsResults = new Dictionary<uint, TransactionResult> ();

    public void IssueOrders(List<OrderAction> actions)
    {
        int count = actions.Count;
        if (count == 0)
        {
            return;
        }
        uint finishUserId = (uint) apiTransactions.counter.Next(count);
        uint startUserId = finishUserId + 1 - (uint) count;

        AutoResetEvent[] events = new AutoResetEvent[count];
        for (int i = 0; i < count; i++)
        {
            var action = actions[i];
            uint userId = startUserId + (uint) i;
            action.UserId = userId;
            var e = new AutoResetEvent(false);
            events[i] = e;
            transactionsEvents[userId] = e;
        }

        for (int i = 0; i < count; i++)
        {
            var action = actions[i];
            apiTransactions.ScheduleOrderAction(action);
        }

        WaitHandle.WaitAll(events);

        // now all answers are available, need to apply information
        foreach (var action in actions)
        {
            UpdateActionWithResult(action, transactionsResults[action.UserId]);
            transactionsResults.Remove(action.UserId);
        }
    }

ScheduleOrderAction将项添加到BlockingCollection。处理器从BlockingCollection执行项目,将结果放入transactionsResults并引发相应的事件。

我的实施有很多问题:

  • 我从不同的线程访问(并修改)字典。例如,当一个线程从transactionResults移除项目时,另一个线程(处理器)可能会向其添加项目。
  • 我不想切换到ConcurentDictionaries,因为即使是字典对我来说已经太贵了(在速度方面)

0 个答案:

没有答案