CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 24
  1. #1
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey Gurus,

    I have a Dialog class that launches a worker thread. Under some circumstances, I want to tell the thread to stop work and exit. To know when the thread has exited cleanly I use SetEvent and WaitForSingleObject. The problem is, I don't seem to be getting the event in my dialog class. My code is as follows:

    Code:
    // My thread parameters
    struct ThreadParams
    {
    HANDLE	threadStopEvent;
    int		threadJob;
    
    // Other variables removed for the sake of brevity
    };
    
    // My thread variables in the header of my dialog class
    DWORD	m_psdbThreadID;
    HANDLE	m_psdbThread;
    HANDLE	m_psdbThreadStopEvent;
    struct ThreadParams m_psdbThreadParams;
    
    // Launch the thread
    m_psdbThreadParams.threadJob = THREAD_UPDATEIMAGES;
    m_psdbThreadStopEvent= CreateEvent( NULL, FALSE, FALSE, NULL );
    m_psdbThreadParams.threadStopEvent = m_psdbThreadStopEvent;
    
    // Launch the job
    m_psdbThread= CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) PSDBThread, &m_ m_psdbThreadParams, 0, &m_psdbThreadID);
    
    // My thread routine
    void PSDBThread( void *param )
    {
    	struct ThreadParams *tp = ( struct ThreadParams * )param;
    
    	bool finished = false;
    
    	switch ( tp->threadJob )
    	{
    		case THREAD_UPDATEIMAGES:
    		{
    			do
    			{
    				// Check for any messages from the main app.
    				while ( PeekMessage( &msg, NULL, THREAD_STOP, THREAD_OK, PM_REMOVE ) )
    				{
    					switch ( msg.message )
    					{
    						case THREAD_STOP:
    						{
    							quit = true;
    						}
    						break;
    
    						case THREAD_PAUSE:
    						{
    							pause = true;
    						}
    						break;
    
    						case THREAD_RESTART:
    						{
    							pause = false;
    						}
    						break;
    
    						default:
    						{
    							DispatchMessage( &msg );
    						}
    						break;
    					}
    				}
    
    				if ( !quit )
    				{
    					// Do stuff until finished
    					finished = true;
    				}
    
    				else break;
    
    				if ( finished ) break;
    
    			} while( true );
    		}
    
    		break;
    	}
    
    	SetEvent( tp->threadStopEvent );
    }
    
    // My code to stop the thread before it has finished its task
    if ( m_psdbThread)
    {
    	PostThreadMessage( m_psdbThreadID, THREAD_STOP, NULL, NULL );
    
    	// Wait for the thread to stop
    	DWORD dwEvent = WaitForSingleObject( m_psdbThreadStopEvent, INFINITE );
    
    	switch ( dwEvent )
    	{
    		case WAIT_OBJECT_0 + 0:
    			// TODO: Perform tasks required by this event
    			printf( "First event was signaled.\n" );
    		break;
    
    		case WAIT_TIMEOUT:
    			printf( "Wait timed out.\n" );
    		break;
    
    		// Return value is invalid.
    		default:
    			printf( "Wait error: %d\n", GetLastError() );
    		break;
    	}
    }
    In the above, my thread runs nicely and exits cleanly on its own, but if I try and stop it WaitForSingleObject never returns. If I change INFINTE to say 3000 (3 secs), then I get WAIT_TIMEOUT.

    Perhaps I am not launching the thread correctly?

    Could someone please give me some advice on what may be going wrong.

    Thanks so much,

    Steve Q.

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Where are you calling WaitForSingleObject? If you are doing that in the UI thread, it's a problem. If you are trying to wait on an object in the UI thread, you need to use MessageWaitForMultipleObjects.

  3. #3
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey Arjay,

    Thanks so much for your reply. Yes, the wait is in the UI. It's in the dialog class that launched the thread.

    I have tried your suggestion, but I still don't seem to get the event. I changed my wait code to this:

    Code:
    HANDLE ghEvents[ 1 ];
    
    ghEvents[ 0 ] =m_psdbThreadStopEvent;
    
    while ( MsgWaitForMultipleObjects( 1, ghEvents, false, INFINITE, QS_ALLEVENTS ) != WAIT_OBJECT_0 );
    It never gets out of the while loop?

    It's almost like my thread stops processing and doesn't set the event because my main dialog is in a wait loop (makes no sense I know)?

    SQ :-)

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    I would say, your approach is unnecessary tricky.

    When you have access to thread event object from both sides, signaler and listener, there's no need in sending messages. The event itself is a message.

    The sample demonstrating my statement:
    HOWTO_stop_thread_safely.zip

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    
    DWORD CALLBACK ThreadProc(LPVOID pVoid)
    {
        DWORD dwRes;
        HANDLE hStop = (HANDLE)pVoid;
    
        while (1)
        {
            dwRes = WaitForSingleObject(hStop, 0);   // #1: test event without impeding thread
    
            switch(dwRes)
            {
            case WAIT_OBJECT_0:
                printf("Leaving thread...\n");
                return 0;
    
            case WAIT_TIMEOUT:
                printf("Doing worker stuff...\n");
                Sleep(10000);
                break;
            }
        }
        return 0;
    }
    
    int main()
    {
        HANDLE hStop = CreateEvent(NULL, TRUE, FALSE, NULL);
        DWORD dwThreadId;
        HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)hStop, 0, &dwThreadId);
    
        printf("Press any key to quit.\n\n");
        while(!kbhit());
        getchar();
    
        printf("Signalling thread to quit...\n");
        SetEvent(hStop);
    
        printf("Waiting for thread shutdown...\n");
        WaitForSingleObject(hThread, INFINITE);   // #2: waiting on thread itself, not event
        printf("App is going down...\n");
        CloseHandle(hThread);
        CloseHandle(hStop);
    
        return 0;
    }
    Code:
    J:\Temp\127>127
    Press any key to quit.
    
    Doing worker stuff...
    Doing worker stuff...
    Doing worker stuff...
    Doing worker stuff...
    Doing worker stuff...
    
    Signalling thread to quit...
    Waiting for thread shutdown...
    Leaving thread...
    App is going down...
    Last edited by Igor Vartanov; September 16th, 2016 at 03:19 AM.
    Best regards,
    Igor

  5. #5
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey Igor,

    Thanks heaps for your help.

    I have tried your suggestion, but with no luck.

    The thread receives the SetEvent from the dialog with no problems, but the dialog always gets stuck in an infinite wait loop. I'm not sure, but the thread seems to stop once I hit the wait in my dialog. Perhaps that is just the debugger though?

    This is really frustrating, as I just can't see what I am doing wrong!

    *EDIT 1* I'm becoming more convinced that the thread stops running when I hit the MsgWaitForMultipleObjects in my main dialog. I did an AfxMessageBox just before the threads ends, and it doesn't get displayed. Is there anything I could be doing that could cause this? (I could also be way of the mark here!)

    *EDIT 2* The thread is not quitting until AFTER the MsgWaitForMultipleObjects, if I put 1000 in instead of INFINITE, the threads starts again after the time has expired. This is why I'm not getting the event. Why does my thread stop processing when I'm in MsgWaitForMultipleObjects?

    Steve :-(
    Last edited by steveq; September 16th, 2016 at 08:34 AM.

  6. #6
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    The only advice I'm able to come up with is: read documentation, use debugger.
    Best regards,
    Igor

  7. #7
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    To try to provide further guidance, it would be helpful to see your code for the main dialog that includes MsgWaitForMultipleObjects() and the current code you have for the thread and dialog.

    I would also suggest that you do the simplest possible program that re-produces the problem and post it here.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Thanks everyone,

    I'll do exactly what 2kaud suggested. I'll write a basic dialog based app that launches a thread and see if it exhibits the same behaviour.

    Watch this space.

    Thanks so much for all your help, it is greatly appreciated.

    Steve Q. :-)

  9. #9
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey All,

    Well I have built a new dialog based MFC application, that just launches a thread, and prints some stuff.

    It exhibits exactly the same behaviour as my other program, as soon as I MsgWaitForMultipleObjects, the thread stops and the dialog goes into an infinite wait loop.

    Here is the souce code, I have also attached the entire solution as a zip file:

    Code:
    // ThreadTestDlg.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "ThreadTest.h"
    #include "ThreadTestDlg.h"
    #include "DlgProxy.h"
    #include "afxdialogex.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    DWORD CALLBACK ThreadProc( void *param );
    
    
    const int THREAD_STOP = WM_APP + 80;
    const int THREAD_PAUSE = WM_APP + 81;
    const int THREAD_RESTART = WM_APP + 82;
    const int THREAD_OK = WM_APP + 83;
    const int THREAD_FINISHED = WM_APP + 84;
    const int THREAD_MESSAGE = WM_APP + 85;
    
    
    // CAboutDlg dialog used for App About
    
    class CAboutDlg : public CDialogEx
    {
    public:
    	CAboutDlg();
    
    // Dialog Data
    	enum { IDD = IDD_ABOUTBOX };
    
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    
    // Implementation
    protected:
    	DECLARE_MESSAGE_MAP()
    };
    
    CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
    {
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange(pDX);
    }
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
    END_MESSAGE_MAP()
    
    
    // CThreadTestDlg dialog
    
    
    IMPLEMENT_DYNAMIC(CThreadTestDlg, CDialogEx);
    
    CThreadTestDlg::CThreadTestDlg(CWnd* pParent /*=NULL*/)
    	: CDialogEx(CThreadTestDlg::IDD, pParent)
    {
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    	m_pAutoProxy = NULL;
    }
    
    CThreadTestDlg::~CThreadTestDlg()
    {
    	// If there is an automation proxy for this dialog, set
    	//  its back pointer to this dialog to NULL, so it knows
    	//  the dialog has been deleted.
    	if (m_pAutoProxy != NULL)
    		m_pAutoProxy->m_pDialog = NULL;
    }
    
    void CThreadTestDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange( pDX );
    	DDX_Control( pDX, IDC_STARTTHREAD, m_startThread );
    	DDX_Control( pDX, IDC_STOPTHREAD, m_stopThread );
    	DDX_Control( pDX, IDC_LISTINFO, m_listInfo );
    }
    
    BEGIN_MESSAGE_MAP(CThreadTestDlg, CDialogEx)
    	ON_WM_SYSCOMMAND()
    	ON_WM_CLOSE()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED( IDC_STARTTHREAD, &CThreadTestDlg::OnBnClickedStartthread )
    	ON_BN_CLICKED( IDC_STOPTHREAD, &CThreadTestDlg::OnBnClickedStopthread )
    	ON_MESSAGE( THREAD_MESSAGE, ThreadMessage )
    END_MESSAGE_MAP()
    
    
    // CThreadTestDlg message handlers
    
    BOOL CThreadTestDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		BOOL bNameValid;
    		CString strAboutMenu;
    		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    		ASSERT(bNameValid);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    
    	// TODO: Add extra initialization here
    	m_thread = NULL;
    
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    void CThreadTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialogEx::OnSysCommand(nID, lParam);
    	}
    }
    
    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.
    
    void CThreadTestDlg::OnPaint()
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialogEx::OnPaint();
    	}
    }
    
    // The system calls this function to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CThreadTestDlg::OnQueryDragIcon()
    {
    	return static_cast<HCURSOR>(m_hIcon);
    }
    
    // Automation servers should not exit when a user closes the UI
    //  if a controller still holds on to one of its objects.  These
    //  message handlers make sure that if the proxy is still in use,
    //  then the UI is hidden but the dialog remains around if it
    //  is dismissed.
    
    void CThreadTestDlg::OnClose()
    {
    	if (CanExit())
    		CDialogEx::OnClose();
    }
    
    void CThreadTestDlg::OnOK()
    {
    	if (CanExit())
    		CDialogEx::OnOK();
    }
    
    void CThreadTestDlg::OnCancel()
    {
    	if (CanExit())
    		CDialogEx::OnCancel();
    }
    
    BOOL CThreadTestDlg::CanExit()
    {
    	// If the proxy object is still around, then the automation
    	//  controller is still holding on to this application.  Leave
    	//  the dialog around, but hide its UI.
    	if (m_pAutoProxy != NULL)
    	{
    		ShowWindow(SW_HIDE);
    		return FALSE;
    	}
    
    	return TRUE;
    }
    
    
    
    void CThreadTestDlg::OnBnClickedStartthread()
    {
    	// TODO: Add your control notification handler code here
    	m_listInfo.ResetContent();
    
    	// Set up the thread parameters
    	m_tp.hWnd = m_hWnd;
    
    	// Launch the job
    	m_thread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) ThreadProc, &m_tp, 0, &m_threadID );
    }
    
    
    void CThreadTestDlg::OnBnClickedStopthread()
    {
    	// TODO: Add your control notification handler code here
    	if ( m_thread )
    	{
    		HANDLE ghEvents[ 1 ];
    
    		PostThreadMessage( m_threadID, THREAD_STOP, NULL, NULL );
    
    		ghEvents[ 0 ] = m_thread;
    
    		while ( MsgWaitForMultipleObjects( 1, ghEvents, false, INFINITE, QS_ALLINPUT ) != WAIT_OBJECT_0 );
    
    		// This NEVER gets called.
    		AfxMessageBox( _T( "MsgWaitForMultipleObjects has returned." ) );
    	}
    }
    
    afx_msg LRESULT CThreadTestDlg::ThreadMessage( WPARAM param1, LPARAM param2 )
    {
    	CString *message = ( CString * ) param2;
    
    	m_listInfo.AddString( *message );
    
    	delete message;
    
    	return false;
    }
    
    DWORD CALLBACK ThreadProc( void *param )
    {
    	MSG msg;
    
    	int count = 0;
    
    	bool quit = false;
    
    	struct ThreadParams *tp = ( struct ThreadParams * )param;
    
    	CString *message;
    
    	message = new CString;
    
    	message->Format( _T( "Thread started..." ) );
    
    	PostMessage( tp->hWnd, THREAD_MESSAGE, NULL, ( LPARAM ) message );
    
    	do
    	{
    		while ( PeekMessage( &msg, NULL, THREAD_STOP, THREAD_MESSAGE, PM_REMOVE ) )
    		{
    			switch ( msg.message )
    			{
    				case THREAD_STOP:
    				{
    					quit = true;
    
    					message = new CString;
    
    					message->Format( _T( "Thread stopping..." ) );
    
    					PostMessage( tp->hWnd, THREAD_MESSAGE, NULL, ( LPARAM ) message );
    				}
    
    				break;
    
    				default:
    				{
    					DispatchMessage( &msg );
    				}
    
    				break;
    			}
    		}
    
    		if ( !quit )
    		{
    			Sleep( 1000 );
    
    			message = new CString;
    
    			message->Format( _T( "Thread processing - loop %d." ), ++count );
    
    			PostMessage( tp->hWnd, THREAD_MESSAGE, NULL, ( LPARAM ) message );
    		}
    
    	} while ( !quit );
    
    	message = new CString;
    
    	message->Format( _T( "Thread exiting." ), ++count );
    
    	PostMessage( tp->hWnd, THREAD_MESSAGE, NULL, ( LPARAM ) message );
    
    	return 1;
    }
    Any ideas?

    Thanks again for all your help.

    Steve Q.

    ThreadTest_SQ.zip

  10. #10
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    It looks like I posted my sample in vain. You keep trying with thread message, don't you?
    Best regards,
    Igor

  11. #11
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Code:
            while ( MsgWaitForMultipleObjects( 1, ghEvents, true, INFINITE, QS_ALLINPUT ) != WAIT_OBJECT_0 );
    This solves your issue.
    Best regards,
    Igor

  12. #12
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Code:
            while ( MsgWaitForMultipleObjects( 1, ghEvents, false, INFINITE, QS_ALLINPUT ) != (WAIT_OBJECT_0 + 1) );
    And this does that too.
    Best regards,
    Igor

  13. #13
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey Igor,

    Your first suggestion worked in my test program, but not in my main program. Very strange.

    This still waits forever:
    Code:
    while ( MsgWaitForMultipleObjects( 1, ghEvents, true, INFINITE, QS_ALLINPUT ) != WAIT_OBJECT_0 );
    and this returns immediately (I put a 5 second sleep in my thread before it exited to make sure my MagWaitForMultipleObjects also waited for 5 secs before returning, alas it returned straight away):
    Code:
    while ( MsgWaitForMultipleObjects( 1, ghEvents, false, INFINITE, QS_ALLINPUT ) != WAIT_OBJECT_0 + 1 );
    I'll have to look a little deeper into my main program to see why it differs from my test program.

    With respect to the thread message, I send multiple messages to my thread, such as STOP, PAUSE, RESTART, RELOAD and there may be more as I further develop my code. I should have made this clearer in my original post. The thread is a background processing task that works while the user continues to use my software. From what I can tell, this appeared to be the most efficient way of passing various messages to the thread. Using an event meant multiple thread parameter variables and multiple CreateEvent calls. Posting a message, means all I have to do is add another thread ID and then case for it in the message loop.

    I'm quite happy to be proven wrong if you still believe an event is a better way of handling it, and I'll modify my code accordingly.

    Thanks so much for you patience and help,

    Steve Q.
    Last edited by steveq; September 17th, 2016 at 09:23 PM.

  14. #14
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Code:
    while ( MsgWaitForMultipleObjects( 1, ghEvents, true, INFINITE, QS_ALLINPUT ) != WAIT_OBJECT_0 );
    The while loop may not be terminating as expected, but what values are being returned by MsgWaitForMultipleObjects()?

    If the parameter bWaitAll is true (as here) then the return value indicates that the state of all specified objects is signalled - ie that the thread has terminated - so as the timeout is INFINITE you shouldn't need to check the return value. What does
    Code:
    MsgWaitForMultipleObjects( 1, ghEvents, true, INFINITE, QS_ALLINPUT );
    do?

    PS
    MsgWaitForMultipleObjects() with bWaitAll true and dwWakeMask set to QS_ALLINPUT will wait until the specified handle is signalled and an input type has occurred. From MSDN
    When bWaitAll is TRUE, the function's wait is completed only when the states of all objects have been set to signaled and an input event has been received.
    so even if the thread has been terminated and the handle signalled, unless an input event also occurs MsgWaitForMultipleObjects(..true..) won't return. This may expalin why it works in the test program but not in the main program.
    Last edited by 2kaud; September 18th, 2016 at 05:10 AM. Reason: PS
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  15. #15
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: MFC - CDialog Not Getting SetEvent with WaitForSingleObject From Thread

    Hey 2kaud,

    Without the while loop, MsgWaitForMultipleObjects still does not return. I changed the code to this:
    Code:
    do
    {
    	dwEvent = MsgWaitForMultipleObjects( 1, ghEvents, true, INFINITE, QS_ALLINPUT );
    
    } while ( dwEvent != WAIT_OBJECT_0 );
    and MsgWaitForMultipleObjects never returned. So I am unable to check the values of dwEvent. If I replace INFINITE with 1000, then dwEvent returns WAIT_TIMEOUT (as you would expect).

    You say:
    MsgWaitForMultipleObjects() with bWaitAll true and dwWakeMask set to QS_ALLINPUT will wait until the specified handle is signalled and an input type has occurred. From MSDN
    Perhaps I should set QS_ALLINPUT to something else?

    Thanks again,

    Steve Q.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured