Добавьте это где-нибудь в вашем коде: (Я обычно помещаю это в статический вспомогательный класс 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());
Это вызывает «customer.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());
}
}
Таким образом, в основном вы создаете все, что вам нужно для вызова, и просто передаете его своему коммуникатору. Это решает вашу необходимость иметь экземпляр или ссылку на потребителя в коммуникаторе.
Также обратите внимание, что я не проверял ничего из этого, я делаю все это в теории, но это должно хорошо работать.