我有一个类Communicator
在后台线程中工作,在 TCP 端口上接收数据。
Communicator 有一个事件 OnDataReceived
这是一个 EventHandler<DataReceivedEventArgs>
类型。
还有一个类Consumer
包含订阅 Communicator.OnDataReceived
的方法事件。
comm.OnDataReceived += consumer.PresentData;
Consumer
类在 Form 构造函数中创建,然后在另一个线程上调用其方法之一。该方法是一个无限循环,因此在应用程序执行期间它一直停留在该方法中。
我想做的是 Communicator.OnDataReceived
调用 consumer.PresentData
的事件消费者线程上的方法。
这几乎是可能的吗?如果是,我应该使用什么样的机制(同步类)?
最佳答案
在您的代码中的某处添加它:(我通常将它放在一个名为 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());
这会在“消费者”上调用“消费者.PresentData”。
至于你的设计问题(consumer references communicator),你可以在communicator中引入一个方法,例如:
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());
}
}
所以基本上您正在创建执行调用所需的一切,并将其传递给您的通信器。这解决了您在通信器中有一个实例或对消费者的引用的必要性。
另请注意,我没有测试任何这些我只是在理论上做这一切,但它应该工作得很好。
关于c# - 在另一个线程中运行事件处理程序(没有线程阻塞),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6615913/