locked
I wanted to know why CreateEvent was used and what is the Necessity of using that in my VC++ application RRS feed

  • Question

  • Hello all,                                            

    In my project CreateThread() function was used to create a worker thread. And then in the Worker thread function ::CreateEvent was used.

    I know that the CreateEvent function is used to create the event thread synchronization object. And also we can use event objects when a thread is supposed to start doing its job after a specified action has occurred.

    But here in the current scenario, I wanted to know why ::CreateEvent() function was used and what is the Necessity of using that?

    Could any one please provide your thoughts on this?

    And also in the below example, we are taking the handle of the ::CreateEvent() and if it is not nulll we are executing the rest of the code.
    And then we are assigning this handle to the newly created HANDLE to a pointer object (*pAllHandles).

    Why we are doing likes this?

    Below is the code snippet:

        //Create the worker thread
        g_hThread = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) &serviceworker_thread, NULL, 0, &dwThreadID);


       // Worker Thread function

    DWORD WINAPI serviceworker_thread (LPVOID pThreadParameter) 
    {
    DWORD errStatus = ERROR_SUCCESS;   


    HANDLE hStopApplicationEvent = ::CreateEvent(0, TRUE, FALSE, APC_STOP_APPLICATION_EVENT_NAME);
    if (hStopApplicationEvent)
        {   

            HANDLE * pAllHandles = new HANDLE;

            assert(pAllHandles != NULL);

            if (pAllHandles)
            {            
                *pAllHandles = hStopApplicationEvent;

                CDaliPowerHandler powerHandler(FIREFLY_SERVICE_WINDOW_CLASS_NAME, FIREFLY_SERVICE_WINDOW_NAME);

                HWND hWnd = powerHandler.GetHwnd();

                SetTimer(hWnd, APC_DEFAULT_INTERVAL, 5000, NULL);
                SetTimer(hWnd, APC_HEARTBEAT_INTERVAL, 3600000, NULL);


                if (hWnd)
                {
                    WaitForMessagesAndEvents(1, pAllHandles, 0, hWnd);
                }
                else
                {
                    assert("worker_thread()" == NULL);
                }
            }
            delete [] pAllHandles;
        }
        else
        {
            assert("worker_thread()" == NULL);
        }

        if (hStopApplicationEvent)
        {
            CloseHandle(hStopApplicationEvent);
        }

        if (hStopLoggingEvent)
        {
            CloseHandle(hStopLoggingEvent);
        }

        return(errStatus);
    }

    And also in WaitForMessagesAndEvents() function, MsgWaitForMultipleObjects is used like as shown below:

    int WaitForMessagesAndEvents (int aTotalNumHandles, HANDLE * pHandlesArray,int aNumTasks, HWND ahWnd) 
    {

      if (ahWnd)
        {          
            ::PeekMessage(&msg, ahWnd, WM_USER, WM_USER, PM_NOREMOVE);
            
            while ((bQuitLoop == FALSE) && (bEventFlag == FALSE))
            {
                res = MsgWaitForMultipleObjects(aTotalNumHandles, pHandlesArray, FALSE, INFINITE, QS_ALLINPUT);
                
                if (res == WAIT_OBJECT_0 + aTotalNumHandles) 
                {
                    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
                    {                    
                       // if (msg.message == WM_QUIT)                     
                         if (msg.message == WM_DESTROY)                     
                        {
                            bQuitLoop = TRUE;
                            exitCode = msg.wParam;
                            //StopAllLaunchedTasks(aNumTasks, pTaskLoaderArray);
                               
                            if (bAdvancedUPS)
                            {
                                InitializeShutdownSetting(TRUE);
                                ///Check to see if we need to disable the alarm on shutdown.
                                TurnOffAlarmsIfUserSettingTrue();
                            }
                            pfc_unregister_9X_service();
                            break;
                        }
    }
    }
    }
    }


    Y A S Prakash

    Wednesday, June 12, 2019 7:16 AM

Answers

  • The name of the event variable should give you a clue as to why it is here.  The code here never sets the event, but notice that the event has a name (APC_STOP_APPLICATION_EVENT_NAME).  That means that some other module, or even some other program, can share access to the event.  If the event gets fired, MsgWaitForMultipleObjects will exit.  I assume you must have omitted some code here, because the "if"statement after MsgWaitForMultipleObjects should have an "else" clause that sets bQuitLoop to TRUE to force the routine to exit.

    The code that does HANDLE * pAllHandles = new HANDLE; is silly, however.  If you really are just passing one event, you can eliminate pAllHandles altogether and just call

    WaitForMessagesAndEvents(1, &hStopApplicationEvent, 0, hWnd)

    Even if you do need multiple events, you don't have to allocate them.  You can just put it on the stack:

        HANDLE pAllHandles[1] = { hStopApplicationEvent };


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Wednesday, June 12, 2019 8:21 PM
  • Hi,

    Thank you for posting here.

    >>I wanted to know why CreateEvent was used and what is the Necessity of using that in my VC++ application

    An event object is like a switch: it has only two states -- on and off. When an event is in the "on" state, we call it "with signal" or otherwise "no signal." You can create an event object in the execution function of a thread, and then observe its state. 

    The handle returned by CreateEvent has the EVENT_ALL_ACCESS access right; it can be used in any function that requires a handle to an event object, provided that the caller has been granted access. 

    The initial state of the event object is specified by the bInitialState parameter.The parameter is FALSE, the initial state of the event object is nonsignaled. We should use the SetEvent function to set the state of an event object to signaled. Use the ResetEvent function to reset the state of an event object to nonsignaled.

    Multiple processes can have handles of the same event object, enabling use of the object for interprocess synchronization.

    For more details, I suggest you could refer to the link: https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-createeventa

    MsgWaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the time-out interval elapses.

    Best Regards,

    Jeanine Zhang

    Wednesday, June 12, 2019 9:00 AM

All replies

  • Hi,

    Thank you for posting here.

    >>I wanted to know why CreateEvent was used and what is the Necessity of using that in my VC++ application

    An event object is like a switch: it has only two states -- on and off. When an event is in the "on" state, we call it "with signal" or otherwise "no signal." You can create an event object in the execution function of a thread, and then observe its state. 

    The handle returned by CreateEvent has the EVENT_ALL_ACCESS access right; it can be used in any function that requires a handle to an event object, provided that the caller has been granted access. 

    The initial state of the event object is specified by the bInitialState parameter.The parameter is FALSE, the initial state of the event object is nonsignaled. We should use the SetEvent function to set the state of an event object to signaled. Use the ResetEvent function to reset the state of an event object to nonsignaled.

    Multiple processes can have handles of the same event object, enabling use of the object for interprocess synchronization.

    For more details, I suggest you could refer to the link: https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-createeventa

    MsgWaitForMultipleObjects function determines whether the wait criteria have been met. If the criteria have not been met, the calling thread enters the wait state until the conditions of the wait criteria have been met or the time-out interval elapses.

    Best Regards,

    Jeanine Zhang

    Wednesday, June 12, 2019 9:00 AM
  • CreateEvent is the Windows API function. When you use .Net, it also uses CreateEvent internally. The code you are showing is using the Windows API. I do not understand why you are asking. Perhaps if you told us what you think it should use instead then we could explain better but hopefully the answer to your question is that the code is doing it the Windows API way.


    Sam Hobbs
    SimpleSamples.Info

    Wednesday, June 12, 2019 7:59 PM
  • The name of the event variable should give you a clue as to why it is here.  The code here never sets the event, but notice that the event has a name (APC_STOP_APPLICATION_EVENT_NAME).  That means that some other module, or even some other program, can share access to the event.  If the event gets fired, MsgWaitForMultipleObjects will exit.  I assume you must have omitted some code here, because the "if"statement after MsgWaitForMultipleObjects should have an "else" clause that sets bQuitLoop to TRUE to force the routine to exit.

    The code that does HANDLE * pAllHandles = new HANDLE; is silly, however.  If you really are just passing one event, you can eliminate pAllHandles altogether and just call

    WaitForMessagesAndEvents(1, &hStopApplicationEvent, 0, hWnd)

    Even if you do need multiple events, you don't have to allocate them.  You can just put it on the stack:

        HANDLE pAllHandles[1] = { hStopApplicationEvent };


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Wednesday, June 12, 2019 8:21 PM