将以下代码添加到您的代码中:(我通常将其放在名为ISynchronizedInvoke的静态帮助类中,这样我就可以调用ISynchronizedInvoke.Invoke(...));
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());
}
}
基本上,您正在创建需要进行调用的所有内容,并将其直接传递给通信器。这解决了在通信器中具有消费者实例或引用的必要性。
还要注意,我没有测试任何内容,我只是在理论上做这些,但应该可以很好地工作。