これをコードのどこかに追加します。
public static void Invoke(ISynchronizeInvoke sync, Action action) {
if (!sync.InvokeRequired) {
action();
}
else {
object[] args = new object[] { };
sync.Invoke(action, args);
}
}
次に、OnDataReceived 内で、次のことができます。
Invoke(consumer, () => consumer.PresentData());
これにより、「consumer」で「consumer.PresentData」が呼び出されます。
設計上の問題 (消費者がコミュニケーターを参照する) については、次のようなコミュニケーター内にメソッドを導入できます。
class Communicator {
private ISynchronizeInvoke sync;
private Action syncAction;
public void SetSync(ISynchronizeInvoke sync, Action action) {
this.sync = sync;
this.syncAction = action;
}
protected virtual void OnDataReceived(...) {
if (!sync.InvokeRequired) {
syncAction();
}
else {
object[] args = new object[] { };
sync.Invoke(action, args);
}
}
}
これにより、コンシューマ クラスから ISynchronizedInvoke を渡すことができます。したがって、コンシューマー アセンブリで ISynchronizedInvoke を作成することになります。
class Consumer {
public void Foo() {
communicator.SetSync(this, () => this.PresentData());
}
}
したがって、基本的には、呼び出しを行うために必要なものをすべて作成し、それをコミュニケーターに渡すだけです。これにより、コミュニケーターでインスタンスまたはコンシューマーへの参照が必要になることが解決されます。
また、私はこれをテストしていないことに注意してください。これはすべて理論的に行っていますが、うまく機能するはずです。