0

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

我已经使用 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(),我做了一些工作,而这些工作会消耗时间。与此同时,另一个事件被触发,并Set()在 genericHandler 再次到达之前被调用WaitOne()。当再次到达 WaitOne 时,它​​会等待另一个Set(),或者如果Set()在到达之前已经调用了 a 则继续WaitOne()

这是在 C# 中实现多个发布者和一个订阅者模式的最佳方式吗?或者我应该使用其他东西而不是 ManualResetEvent?

注意:genericHandler 位于不同的线程中,因为 Event1 和 Event2 具有不同的优先级,所以在处理程序中我检查 Event1 是否有待处理的工作,然后再检查 Event2。

4

2 回答 2

0

问题和代码的呈现方式过于模糊,无法提供好的、具体的建议。那就是说...

不,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...集合。

于 2014-11-04T17:56:40.833 回答
0

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

于 2014-11-04T17:56:52.613 回答