missing events when using MsgWaitForMultipleObjectsEx

Hi everyone!

I am missing some events when executing 'MsgWaitForMultipleObjectsEx'. If you execute this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <atomic>

static std::atomic<bool> stopSignal;
HANDLE ghEvents[2];

static void run()
{
    // Wait for the thread to signal one of the event objects
    DWORD dwEvent;
    while (stopSignal.load() == false)
    {
        dwEvent = MsgWaitForMultipleObjectsEx(2, ghEvents, INFINITE, QS_ALLEVENTS, 0);       

        switch (dwEvent)
        {
            // ghEvents[0] was signaled
        case WAIT_OBJECT_0 + 0:
            printf("First event was signaled.\n");
            break;
            // ghEvents[1] was signaled
        case WAIT_OBJECT_0 + 1:
            printf("Second event was signaled.\n");
            break;
            // Return value is invalid.
        default:
            printf("Wait error: %d\n", GetLastError());
            ExitProcess(0);
        }
    }
}

int main(void)
{
    int i;
    stopSignal.exchange(false);

    for (i = 0; i < 2; i++)
    {
        ghEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL); 
    }
    printf("0 to stop\n");
    printf("> 0 to send 50 events\n\n");
    std::thread threadRun(run);
    while (stopSignal.load() == false)
    {
        std::cin >> i;
        if (i == 0)
        {
            stopSignal.exchange(true);
            SetEvent(ghEvents[0]);
        }
        else
        {
            for (size_t j = 0; j < 50; ++j)
            {
                SetEvent(ghEvents[1]);
            }
        }
    }

    threadRun.join();
    // Close event handles
    for (i = 0; i < 2; i++)
        CloseHandle(ghEvents[i]);

    return 0;
}



and input an integer greater than 0 to send 50 events, you will see that 'MsgWaitForMultipleObjectsEx' only processes two events, missing the 48 events left. Why?? How can I capture all events??

Thanks in advance!!
The thread that checks the event runs asynchronously with the code that sets it repeatedly in a loop without waiting. It is almost certainly going to miss some, it seems you're expecting some kind of synchronization, but that doesn't happen here.
An event must be reset (by the wait-function) before SetEvent(...) can signal a new event. The question is: Is it really relevant that MsgWaitForMultipleObjectsEx(...) returns 50 times?

See:

https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-setevent

Setting an event that is already set has no effect.
Last edited on
Hello kbw, coder777!

What I was expecting is 'MsgWaitForMultipleObjectsEx' to behave like an event queue (pretty much like 'epoll_event' in Linux).

Even though the main thread sets repeatedly events, I want those events to be queued so they are not lost.

Should I use other calls instead of 'MsgWaitForMultipleObjectsEx' and/or 'SetEvent'??

Thanks a lot!
An event is either signaled or not. So it does not contain any counter. A semaphore does. See:

https://docs.microsoft.com/en-us/windows/desktop/sync/semaphore-objects

But I would think it is not what you want. Thus you need to make your own queue. There might even be more connected then just the count.

You might consider using condition_variable that comes with c++:

http://www.cplusplus.com/reference/condition_variable/
Hi coder777, you were right, that's not what I wanted and I think I just found the solution : APC calls and 'QueueUserAPC' to queue events. If you execute this code now all events are being processed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <atomic>

static std::atomic<bool> stopSignal;
HANDLE ghEvents[3];
HANDLE thread_handle;


DWORD WINAPI run(LPVOID lpParam)
{
    // Wait for the thread to signal one of the event objects
    DWORD dwEvent;
    while (stopSignal.load() == false)
    {
        dwEvent = MsgWaitForMultipleObjectsEx(3, ghEvents, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
        if (dwEvent != WAIT_IO_COMPLETION)
        {
            switch (dwEvent)
            {
                // ghEvents[0] was signaled
            case WAIT_OBJECT_0 + 0:
                printf("First event was signaled.\n");
                break;
                // ghEvents[1] was signaled
            case WAIT_OBJECT_0 + 1:
                printf("Second event was signaled.\n");
                break;
                // Return value is invalid.
            default:
                printf("Wait error: %d\n", GetLastError());
                ExitProcess(0);
            }
        }
    }
    return 0;
}

VOID CALLBACK apc_function_1(ULONG_PTR dwParam) 
{
    size_t* obj = (size_t*)dwParam;
    printf("processing %d\n", *obj);
}

int main(void)
{
    int i;
    stopSignal.exchange(false);
    DWORD thread_id;
    for (i = 0; i < 2; i++)
    {
        ghEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL); 
    }
    printf("0 to stop\n");
    printf("> 0 to send 50 events\n\n");
    thread_handle = CreateThread(NULL, 0, run, NULL, 0, &thread_id);
    ghEvents[2] = thread_handle;
    size_t* value;
    while (stopSignal.load() == false)
    {
        std::cin >> i;
        if (i == 0)
        {
            stopSignal.exchange(true);
            SetEvent(ghEvents[0]);
        }
        else
        {
            for (size_t j = 0; j < 50; ++j)
            {
                value = new size_t;
                *value = j + 1;
                QueueUserAPC(apc_function_1, thread_handle, (ULONG_PTR)value);
            }
        }
    }
    WaitForMultipleObjects(1, &thread_handle, TRUE, INFINITE);
    
    // Close event handles
    for (i = 0; i < 3; i++)
        CloseHandle(ghEvents[i]);

    return 0;
}
Topic archived. No new replies allowed.