在你的代码中添加这个:(我通常把它放在一个名为 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());
}
}
因此,基本上您正在创建执行调用所需的一切,并将其传递给您的通信器。这解决了您在通信器中拥有实例或引用消费者的必要性。
另请注意,我没有测试任何这些我在理论上都在做这一切,但它应该可以很好地工作。