1

私は取引ソフトウェアを書いています。私のシステムは、処理する必要がある「順次アイテム」(1、2、3...) を生成します (私のアプリケーションでは、各アイテムは実行の順序であり、ID は内部注文 ID と呼ばれます)。

アイテムを生成できるスレッドが多数あります (多くの戦略) が、各アイテムが 1 回だけ生成されることが保証されています

必要なプロセッサー (注文執行者) は 1 つだけです。

  • 新しいアイテムが利用可能になるたびに、実行のために送信します(注文します)
  • コールバックで結果を受け取り、「アイテム結果」を更新します(証券取引所からの応答を取得します)

各生産者は

  • 実行する項目の「順次パック」を送信します (たとえば、「1234,1235,1236,1237」を送信します)。
  • すべてのアイテムの結果が利用可能になるまでブロックします。すべてのアイテムの結果が利用可能になったとき - プロセス

ご了承ください:

  • アイテムは別のスレッドから並行して送信できます
  • 最小限の遅延と最小限の「ロック」が必要です
  • C++ への移植が容易なコードがあると便利です
  • いつでも、かなり「限られた」数の「ライブ」IDを持っています。たとえば、ライブIDの「1と10000」を同時に持つことはできません。新しい ID が作成されるたびに、処理してクリーンアップする必要があるためです。したがって、私は常に互いに近いIDのセットを持っています(たとえば、〜9900-10000)。したがって、実装に cycle-array を使用することはおそらく理にかなっています

何か提案できる場合は、提案してください。以下に奇妙な実装を追加しますが、読む必要はありません。


これは私の問題の実装です:

    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);
        }
    }

ScheduleOrderActionBlockingCollection にアイテムを追加します。プロセッサーは BlockingCollection からアイテムを実行し、結果を transactionsResults に入れ、対応するイベントを発生させます。

私の実装には多くの問題があります。

  • さまざまなスレッドから辞書にアクセス (および変更) します。たとえば、あるスレッドがtransactionResults別のスレッド (プロセッサ) からアイテムを削除すると、それにアイテムが追加される場合があります。
  • 私は ConcurentDictionaries に切り替えたくありません。Dictionary でさえも (速度の点で) 私にとっては高すぎるからです。
4

0 に答える 0