3


1

C#複数のソース、異なるスレッド、1つのイベントハンドラー

スレッディングとイベントレイジングのスキルが高い人が必要です。

抽象クラス A`と2つの具象クラス C1`、 C2(プラグインなど)があります。

「plugin-application」「plugin-plugin」通信など、相互に通信する必要があるため、これを実現する抽象クラスにメソッド「ExecuteCommand」があります。 この関数は、特定のコマンドを処理して結果を返すために、アプリケーションに「イベント」を発生させます(たとえば、1つのプラグインがアプリからのデータを必要とする場合、ベースから「ExecuteCommand」を呼び出し、イベントハンドラーに付属する結果を待ちますアプリケーションで処理されます)。

protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
{
  // this code has been simplified
  SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);

  // generate processing command event (it requires to fill in the result)
  OnProcessingAppCommand(this, eventArgs);

  return eventArgs.OutputParamsList;
}

問題は:

C1`と C2`のそれぞれに異なるスレッドがあり、それぞれのスレッド内から同時に `ExecuteCommand`を呼び出す場合、デザインが破損し、返される結果は予期しないものになります。

このシナリオに最適な設計は何ですか? 「AsyncOperation」を使用するなど、「ExecuteCommand」非同期呼び出し内で使用することを考えていました…​ しかし、それは正しい方法ですか?

_edited:_私は探していると思います:同期または非同期の方法は私のシナリオに適していますか? または、アプリのイベントハンドラーをプラグインのスレッド内で処理するか、メインスレッドのどこかで同期させますか?

私はあなたの推薦のためのいくつかの良い説明を本当に感謝します

ありがとうございました。

1 Answer


1


共通のリソースまたはコードブロックでスレッド同期を行う通常の簡単な方法は、ミューテックス(または、この場合はクリティカルセクション)を使用することです。 lockステートメントを使用します。

この記事では「this」ポインターをロックするように記述されていますが、外部の呼び出し元が同じロックを取得してプログラムを破壊する可能性があるため、危険です。 プライベートクラス変数をロックします。

次に、ロック/クリティカルセクションを組み込むためのサンプルコードのいくつかの変更を示します。

class SomeClass : ISomeInterface
{
  protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
  {
    lock(executeCommandLock)
    {
      SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);
      OnProcessingAppCommand(this, eventArgs);
      return eventArgs.OutputParamsList;
    }
  }

  private Object executeCommandLock = new Object();
}

編集:

(コメントからの言い換え)。 単一のスレッドでExecuteCommandのすべての呼び出しを非同期的に処理することをお勧めします。 Dispatcherクラスでこれを実現できる場合があります。

1つのスレッドでディスパッチャーへの参照を取得します。 その参照を他のスレッドに渡します。 これらのスレッドがExecuteCommandを呼び出したい場合、dispatcher.BeginInvokeを使用します。 BeginInvokeを使用するため、ExecuteCommandの呼び出しはすべて非同期的に動作し、そのスレッドでブロックされません。 ただし、ExecuteCommandの各バージョンはキューに入れられ、順次ディスパッチャスレッドを実行します。