在没有ResetEvent的情况下调用setEvent [英] setEvent is called without ResetEvent

查看:328
本文介绍了在没有ResetEvent的情况下调用setEvent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果使用setEvent设置手动复位事件但不使用ResetEvent复位则会发生什么情况;并且该事件被触发多次。

what happens if a manual-reset event is set using setEvent but not reset using ResetEvent; and that event is triggered multiple times.i.e. while the event is getting processed, again the event is set.

以下是示例任务:

void foo()
{
...
   SetEvent(hEvent1);
...
}
void foo1()
{
...
SetEvent(hEvent2);
...
}
int MainHandler()
{
...
 dwEvent = WaitForMultipleObjects(2,
 ghEvents,     // array of objects
 FALSE,       // wait for any object
 5000); 
switch(dwEvent)
{
case hEvent1:
//do something
break;
case hEvent2:
//do something
break;
}
}

现在,假设hEvent1的情况正在执行仍然设置),不知何故再次触发hEvent1。我故意不把ResetEvent(hEvent1),即使它是手动重置事件。

Now, suppose while hEvent1's case is executing(i.e. it is still set), somehow again hEvent1 is triggered. I have deliberately not put ResetEvent(hEvent1) even though it is a manual-reset events. So, do we have a race condition?

推荐答案

在您的示例中使用 WaitForMultipleObjects ,如果您正在等待的事件未按事件句柄数组中频率的升序列出,则可能存在潜在问题。还要注意我的注释,上面的代码假设 WaitForMultipleObjects 返回一个事件句柄。它不会。

In your example using WaitForMultipleObjects, you may have a potential problem if the events you are waiting on are not listed in increasing order of frequency in the array of event handles. Also note my comment that your code above assumes that WaitForMultipleObjects returns an event handle. It doesn't.

WaitForMultipleObjects 会在第一个看到,从索引零向上看数组。

WaitForMultipleObjects will stop waiting when the first signaled event is seen, looking at the array from index zero upwards.

所以如果你有一个事件被设置(或没有得到重置)作为数组中的第一个条目,那么其他事件将被饥饿可见)。

So if you have an event that gets set (or does not get reset) as the first entry in the array, then the other events will get starved (i.e. will never be seen).

因此,在您的示例中,只要 hEvent1 仍然发出信号, hEvent2 将不会被看到。

So, in your example, as long as hEvent1 is still signaled, hEvent2 will not be seen.

作为一个常见模式的例子,假设我们有一些工作线程,其线程函数已被路由回一些拥有包含事件对象和互斥体的任何类。工作线程只响应两个事件 - 一个请求关闭,一个请求做一些工作。代码可能如下所示:

As an example of a common pattern, suppose we have some worker thread, whose thread function has been routed back to some owning class that contains the event objects and mutexes or whatever. The worker thread responds to just two events - a request to close tidily and a request to do some work. The code might look something like this:

UINT CMyClass::ThreadFunc()
{
    // make an array of some interesting event handles
    HANDLE hEvents[2] = { m_hKillEvent, m_hWorkEvent };

    // main loop - do work until killed
    while (true)
    {
        // wait for either event
        DWORD dwRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);

        // see why we got signalled
        if (dwRet == WAIT_OBJECT_0)
        {
            // kill requested - exit loop
            break;
        }
        else if (dwRet == WAIT_OBJECT_0 + 1)
        {
            // work requested - do some work here
        }
        else
        {
            // error handling - bad handles?
        }
    }

    // normal exit
    return 0;
}

编码后,这将正常工作 - 主线程调用 SetEvent(m_hWorkEvent)来触发后台线程做一些工作,它调用 SetEvent(m_hKillEvent)如果线程正在工作,关闭可能会有一些超时保护,例如:

As coded, this will work fine - the main thread calls SetEvent(m_hWorkEvent) to trigger the background thread to do some work and it calls SetEvent(m_hKillEvent) to make the worker thread close. Closing may be protected with some timeout in case the thread is mid-work, so something like:

// close worker thread
SetEvent(m_hKillEvent);

// wait for thread to die peacefully
DWORD dwRet = WaitForSingleObject(m_hWorkerThread, 5000);
if (dwRet == WAIT_TIMEOUT)
{
    // worker failed to respond - error handling here
}

现在,这个关闭的进程会正常工作,即使 m_hWorkEvent 被频繁地发出信号 - 例如,时间在这里做一些工作已经完成,事件再次发出信号。这是因为 WaitForMultipleObjects 将始终首先检查kill事件,因为它是数组中的第一个

Now, this closedown process will work fine, even if m_hWorkEvent is being signalled very frequently - for example, by the time do some work here has finished, the event has again been signalled. This is because WaitForMultipleObjects will always check the kill event first because it is the first one in the array.

但是,如果数组定义如下:

However, if the array had been defined like this:

    // make an array of some interesting event handles
    HANDLE hEvents[2] = { m_hWorkEvent, m_hKillEvent };

如果 m_hWorkEvent 它在长时间运行期间再次设置,或者它是手动重置事件,并且您从不重置它),那么线程将从不 cleanly退出,因为它永远不会看到kill信号。它总是尝试先做一些工作。

And if m_hWorkEvent is continually signalled (e.g. it gets set again during a long-running do some work here, or it is a manual reset event and you never reset it), then the thread will never exit cleanly because it will never see the kill signal. It will always try to do some work first.

这是我的意思是按照频率的递增顺序排列数组中的事件。 kill事件具有最低频率(它只发出一次信号),因此它首先。如果您有三个或更多不同工作请求的事件,您需要保持相同的顺序,否则一些事件将被饥饿。

This is what I mean about ordering the events in the array in increasing order of frequency. The kill event has the lowest frequency (it is signaled only once), so it goes first. If you have three or more events for different work requests, you need to maintain the same ordering or some events will get starved.

无论您决定做什么,注意,即使 WaitForMultipleObjects 在错误事件上发布,您仍然可以通过等待零超时来检查是否发送了特定事件:

Whatever you decide to do, it's also worth noting that even if WaitForMultipleObjects got release on the "wrong" event, you can still check if a particular event is signaled by waiting with a zero timeout:

if (WaitForSingleObject(hSomeEvent, 0) == WAIT_OBJECT_0)
{
    // ... hSomeEvent was signaled
}

这可以允许您对长时间运行的合适部分中的kill事件进行中间检查,运行后台工作程序。

This can allow you to put intermediate checks for a kill event in suitable parts of a long-running background work procedure.

这篇关于在没有ResetEvent的情况下调用setEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆