私は一連の Win64 コンソール アプリを持っています。1 つが「マスター」で、16 個が「スレーブ」です。
このロジックの元のバージョンには実行可能ファイルが 1 つしかありませんでした。この実行可能ファイルは、コマンド ライン パラメーター「init」で起動すると、非常に大きなデータ セット (3 ギガ) を初期化し、Windows メッセージ ポンプに座って、その大きなデータ セットの分析を要求するメッセージを待ちます。 . データセットの分析が必要な場合、その同じ実行可能ファイルが分析要求パラメーターを使用して起動され、新しく起動された実行可能ファイルは、それ自体の既に初期化されたインスタンスのウィンドウ ハンドルを見つけ、分析要求とパラメーターを既に初期化されているインスタンスに送信します。 Windows メッセージ WM_COPYDATA。これは、単一の実行可能なアーキテクチャの魅力のように機能します。
しかし、今ではより強力なシステムを手に入れたので、複数の解析実行可能ファイルをそれぞれ別のコアで一度に実行したいと考えています。そこで、「マスター」として機能するマネージャ コンソール アプリケーションの「スレーブ」として機能する 16 個の分析実行可能ファイルがある新しいアーキテクチャを作成しました。(参考までに、1 つの分析リクエストには 0.5 秒から 4.0 秒かかることがあります。そのため、一度に複数のリクエストを実行したいのです。)
Windows メッセージを通信手段として引き続き使用している場合、SendMessage() を使用すると、メッセージが受信者によって処理されるまで発信者がブロックされます。これらのメッセージを同時に処理したいので、それは良くありません。そこで、SendMessageCallback() や SendNotifyMessage() などの非同期 Windows メッセージ関数を使用してみました。それらは、同時にではなく、ブロックする方法で失敗または実行されました。
さらに調査を重ねた結果、実行可能ファイル (基本的にはメモリ マップ ファイル) 間の通信手段として「名前付き共有メモリ」にたどり着きました。これをセットアップすると、マスターが名前付き共有メモリ ブロックを作成できるようになり、すべての実行可能ファイルが同じメモリのビューを要求できるようになり、名前付き共有メモリ内のデータを処理するステート マシンを介して、マスターとスレーブ間で同期をとります。
ただし、マスターとスレーブが継続的に実行されていないように見えます。
私はまだマスターが分析パラメーターを保持するコマンドラインを介して起動されるという基本的な考え方を使用しています。その実行可能ファイルは、名前付き共有メモリのセットアップとすべてのスレーブの現在の状態を使用して、既に実行されているバージョンのそれ自体にメッセージを送信し、次に使用可能なスレーブが選択され、名前付き共有メモリの常駐ステート マシンが分析要求を受け取ります。
この部分は正常に動作しています。ただし、変更した Windows メッセージ ループがループしていないように見えるため、スレーブはスリープ状態またはその他の休止状態にあるように見えます。
現在の Windows メッセージ処理ループは次のようになります。
while (1) {
int status = ::GetMessage(&msg, 0, 0, 0);
if (status != 0) {
if (status == -1) return -1
::DispatchMessage(&msg);
}
else if (status == 0)
break;
HandleSharedMemoryDeliveredTasks(); // NOTE: checking Named Shared Memory
}
このループ内にブレーク ポイントを配置しても、Windows メッセージが受信されない限り、トリガーされません。
それで、名前付き共有メモリのチェックが(ブロッキング)メッセージを送信せずに続行されるように、ループを存続させる方法を考えています。
マスターとスレーブの実行可能ファイルを Windows サービスに変換する必要がある問題領域で作業していることを認識しています。しかし、私はこれを機能させることに非常に近づいており (どうやら)、Windows サービスへの書き換えは私が経験したことのない領域です。
また、実行可能ファイルでこれを使用して、それらをアクティブに保ちます(ただし、役に立たないようです):
// during program init:
SetThreadExecutationState(ES_CONTINIOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED);
マスターがステートマシンを作業用に設定するときにスレーブを非同期に「ウェイクアップ」し、作業が完了したときにスレーブにマスターを「ウェイクアップ」させる方法について何か提案はありますか?