C#事件多个发布服务器到一个订阅服务器

本文关键字:服务器 一个 事件 | 更新日期: 2023-09-27 18:29:17

我有一段代码,它有两个事件处理程序。我希望这两个事件处理程序通知另一个方法还有一些工作要做。

我已经使用ManualResetEvent实现了这一点,但我不确定这是否是实现我想要的最好方法,或者是否有更好的方法。

static ManualResetEvent autoEvent = new ManualResetEvent(false);
void begin() {
    ThreadPool.QueueUserWorkItem(new WaitCallback(genericHandler));
}
void OnEvent1(object sender) {
    autoEvent.Set();
}
void OnEvent2(object sender) {
    autoEvent.Set();
}
void genericHandler(object info) {
    while (true) {
        autoEvent.WaitOne();
        // do some work
    }
}

我遇到的最重要的问题之一是:autoEvent.WaitOne()之后,我会做一些工作,而这些工作会消耗时间。同时,触发另一个事件,在genericHandler再次到达WaitOne()之前调用Set()。当再次到达WaitOne时,它会等待另一个Set()吗?如果在到达WaitOne()之前调用了Set(),它会继续吗?

这是在C#中实现多个发布者和一个订阅者模式的最佳方式吗?或者我应该使用另一个东西而不是手动重置事件吗?

注意:genericHandler在不同的线程中,因为Event1和Event2有不同的优先级,所以在检查Event2之前,我会在处理程序中检查Event1是否有挂起的工作。

C#事件多个发布服务器到一个订阅服务器

您的代码确实做了您认为它做的事情,并且您描述的竞赛条件根本不是问题。根据MRE的文档,当它被设置时,它将保持在"信号"状态,直到它被调用WaitOne重置。

问题和代码呈现得太模糊,无法提供好的、具体的建议。也就是说。。。

不,此处不适合使用ManualResetEvent。它不仅使代码不必要地复杂化,而且您的代码依赖于从线程池中获取的长时间运行的线程(只应在其中执行短暂的任务)。

如果您需要事件来触发某些异步工作的执行,那么您应该使用async/await模式,其中每个新的工作单元都通过Task类调用。

例如:

async void OnEvent1(object sender) {
    var workUnit = ... ; // something here that represents your unit of work
    await Task.Run(() => genericHandler(workUnit));
}
void OnEvent2(object sender) {
    var workUnit = ... ; // something here that represents your unit of work
    await Task.Run(() => genericHandler(workUnit));
}
void genericHandler(object info) {
    // do some work using info
}

注意,事件对象和begin()方法被完全消除。

从你的问题中还不清楚每个工作单元是否完全独立。如果没有,那么您可能还需要一些同步来保护共享数据。同样,如果没有更具体的问题,就不可能说出这将是什么,但很可能您会使用lock语句或Concurrent...集合之一。

相关文章: