在另一个线程中运行事件处理程序(没有线程阻塞)
本文关键字:线程 程序 另一个 运行 事件处理 | 更新日期: 2023-09-27 18:01:42
我有一个类Communicator
,在后台线程中工作,在TCP端口上接收数据。
通信器存在EventHandler<DataReceivedEventArgs>
类型的事件OnDataReceived
。
还有一个类Consumer
,它包含一个订阅Communicator.OnDataReceived
事件的方法。
comm.OnDataReceived += consumer.PresentData;
Consumer
类是在Form构造函数中创建的,然后在另一个线程中调用它的一个方法。此方法是一个无限循环,因此在应用程序执行期间,它将留在该方法中。
我想做的是让Communicator.OnDataReceived
事件调用消费者线程上的consumer.PresentData
方法。
这有可能吗?如果是,我应该使用什么样的机制(同步类)?
将此添加到代码中的某个地方:(我通常将其放在名为ISynchronizedInvoke的静态helper类中,因此我可以调用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 '。关于"消费者"的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);
}
}
}
这将为您提供一种从消费者类传入isynsynchronizedinvoke的方法。因此,您将在使用者程序集中创建isynsynchronizedinvoke。
class Consumer {
public void Foo() {
communicator.SetSync(this, () => this.PresentData());
}
}
基本上你在创建所有你需要做调用的东西,并把它传递给你的通信器。这解决了在通信器中使用消费者实例或引用的必要性。
还要注意的是,我并没有测试这些,我只是在理论上这么做,但它应该可以很好地工作。
尝试使用BackgroundWorker类
这应该是可能的。您可以创建一个队列来执行,或者查看Dispatcher对象,如果有帮助的话,将一些方法推入UI线程是有用的(有时是强制性的,是唯一的方法)。
只有当目标线程设计为接受封送操作,将方法的执行从初始线程转移到目标线程时,才能在线程上执行方法。
让这个工作的一种方法是让你的Consumer
类实现ISynchronizeInvoke
。然后让Communicator
类接受一个ISynchronizeInvoke
实例,它可以使用该实例执行封送处理操作。以System.Timers.Timer
类为例。System.Timers.Timer
具有SynchronizingObject
属性,它可以通过调用ISynchronizeInvoke.Invoke
或ISynchronizeInvoke.BeginInvoke
将Elapsed
事件封送到承载同步对象的线程上。
棘手的部分是如何在Consumer
类上实现ISynchronizeInvoke
。由该类启动的工作线程必须实现生产者-消费者模式才能处理委托。BlockingCollection
类将使这相对容易,但仍然有相当的学习曲线。试一试,如果你需要更多的帮助,再回复一个更有针对性的问题。