Sending windows message from worker thread
-
Hello, I am currently getting to grips with MFC, VC++, VS2010 and threading. In particular I am trying to start a thread from a CMainFrame object, then post a windows message from the thread back to he CMainFrame object such that a messagebox can be displayed indicating the progress of the thread. In this example the uses starts the thread from a drop-down menu item (CreateWorkerThread function is called) the thread code executes and sends a single windows message towards the end of the thread. The problem I have is that CMainFrame doesn't seem to respond to the message unless the function that starts the thread uses a ::WaitForSingleObject() call. Why do I need to effectively pause the execution of the function creating the thread? Mayby naively, I assumed the following actions: -User selects Menu item -CreateWorkerThread() is called -Thread executes in parallel with the remains of CreateWorkerThread() -Worker thread generates a windows message (using ::PostMessage()) -By now CreateWorkerThread() would have completed. -CMainFrame Message map processes Worker Thread' message 'WM_THREAD1MSG' -Messagebox created and presented to user.
void CMainFrame::CreateWorkerThread(void)
// Created 25FEB2011
{HWND hWnd = GetSafeHwnd(); if (hWnd == NULL) { TRACE0("Window pointer is invalid!"); } hWnd = GetSafeHwnd(); //hWnd has been made a 'public' member pThread1 = AfxBeginThread(mcProc, static\_cast<LPVOID>(&hWnd), THREAD\_PRIORITY\_NORMAL, 0, CREATE\_SUSPENDED); pThread1 ->ResumeThread(); DWORD ThreadExitCodeValue = 0; LPDWORD pDWord = NULL; pDWord = &ThreadExitCodeValue; //Need a handle for the thread: HANDLE pThreadHandle = pThread1->m\_hThread; ::WaitForSingleObject(pThreadHandle,INFINITE); //stops this 'thread' until worker thread exits.
}
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
ON_WM_CREATE()ON\_MESSAGE(WM\_THREAD1MSG, Respond2ThreadMsg) //#define WM\_THREAD1MSG WM\_APP + 0x10 <- this line included in stdafx.h ON\_COMMAND(ID\_VIEW\_CUSTOMIZE, &CMainFrame::OnViewCustomize) ON\_REGISTERED\_MESSAGE(AFX\_WM\_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew) ON\_COMMAND\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnApplicationLook) ON\_UPDATE\_COMMAND\_UI\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnUpdateApplicationLook) ON\_COMMAND(ID\_GCCODEDVMT\_TESTCOMMAND, TestCommand) //GC added 23FEB2011 ON\_COMMAND(ID\_GCCODEDVMT\_CREATEWORKERTHREAD, C
-
Hello, I am currently getting to grips with MFC, VC++, VS2010 and threading. In particular I am trying to start a thread from a CMainFrame object, then post a windows message from the thread back to he CMainFrame object such that a messagebox can be displayed indicating the progress of the thread. In this example the uses starts the thread from a drop-down menu item (CreateWorkerThread function is called) the thread code executes and sends a single windows message towards the end of the thread. The problem I have is that CMainFrame doesn't seem to respond to the message unless the function that starts the thread uses a ::WaitForSingleObject() call. Why do I need to effectively pause the execution of the function creating the thread? Mayby naively, I assumed the following actions: -User selects Menu item -CreateWorkerThread() is called -Thread executes in parallel with the remains of CreateWorkerThread() -Worker thread generates a windows message (using ::PostMessage()) -By now CreateWorkerThread() would have completed. -CMainFrame Message map processes Worker Thread' message 'WM_THREAD1MSG' -Messagebox created and presented to user.
void CMainFrame::CreateWorkerThread(void)
// Created 25FEB2011
{HWND hWnd = GetSafeHwnd(); if (hWnd == NULL) { TRACE0("Window pointer is invalid!"); } hWnd = GetSafeHwnd(); //hWnd has been made a 'public' member pThread1 = AfxBeginThread(mcProc, static\_cast<LPVOID>(&hWnd), THREAD\_PRIORITY\_NORMAL, 0, CREATE\_SUSPENDED); pThread1 ->ResumeThread(); DWORD ThreadExitCodeValue = 0; LPDWORD pDWord = NULL; pDWord = &ThreadExitCodeValue; //Need a handle for the thread: HANDLE pThreadHandle = pThread1->m\_hThread; ::WaitForSingleObject(pThreadHandle,INFINITE); //stops this 'thread' until worker thread exits.
}
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
ON_WM_CREATE()ON\_MESSAGE(WM\_THREAD1MSG, Respond2ThreadMsg) //#define WM\_THREAD1MSG WM\_APP + 0x10 <- this line included in stdafx.h ON\_COMMAND(ID\_VIEW\_CUSTOMIZE, &CMainFrame::OnViewCustomize) ON\_REGISTERED\_MESSAGE(AFX\_WM\_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew) ON\_COMMAND\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnApplicationLook) ON\_UPDATE\_COMMAND\_UI\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnUpdateApplicationLook) ON\_COMMAND(ID\_GCCODEDVMT\_TESTCOMMAND, TestCommand) //GC added 23FEB2011 ON\_COMMAND(ID\_GCCODEDVMT\_CREATEWORKERTHREAD, C
You're passing the address of a temporary variable to the thread: when
CreateWorkerThread
exits,hWnd
goes out of scope. BTW: There is really no need to pass a pointer to theHWND
, just pass theHWND
value. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
You're passing the address of a temporary variable to the thread: when
CreateWorkerThread
exits,hWnd
goes out of scope. BTW: There is really no need to pass a pointer to theHWND
, just pass theHWND
value. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
Hello, I am currently getting to grips with MFC, VC++, VS2010 and threading. In particular I am trying to start a thread from a CMainFrame object, then post a windows message from the thread back to he CMainFrame object such that a messagebox can be displayed indicating the progress of the thread. In this example the uses starts the thread from a drop-down menu item (CreateWorkerThread function is called) the thread code executes and sends a single windows message towards the end of the thread. The problem I have is that CMainFrame doesn't seem to respond to the message unless the function that starts the thread uses a ::WaitForSingleObject() call. Why do I need to effectively pause the execution of the function creating the thread? Mayby naively, I assumed the following actions: -User selects Menu item -CreateWorkerThread() is called -Thread executes in parallel with the remains of CreateWorkerThread() -Worker thread generates a windows message (using ::PostMessage()) -By now CreateWorkerThread() would have completed. -CMainFrame Message map processes Worker Thread' message 'WM_THREAD1MSG' -Messagebox created and presented to user.
void CMainFrame::CreateWorkerThread(void)
// Created 25FEB2011
{HWND hWnd = GetSafeHwnd(); if (hWnd == NULL) { TRACE0("Window pointer is invalid!"); } hWnd = GetSafeHwnd(); //hWnd has been made a 'public' member pThread1 = AfxBeginThread(mcProc, static\_cast<LPVOID>(&hWnd), THREAD\_PRIORITY\_NORMAL, 0, CREATE\_SUSPENDED); pThread1 ->ResumeThread(); DWORD ThreadExitCodeValue = 0; LPDWORD pDWord = NULL; pDWord = &ThreadExitCodeValue; //Need a handle for the thread: HANDLE pThreadHandle = pThread1->m\_hThread; ::WaitForSingleObject(pThreadHandle,INFINITE); //stops this 'thread' until worker thread exits.
}
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
ON_WM_CREATE()ON\_MESSAGE(WM\_THREAD1MSG, Respond2ThreadMsg) //#define WM\_THREAD1MSG WM\_APP + 0x10 <- this line included in stdafx.h ON\_COMMAND(ID\_VIEW\_CUSTOMIZE, &CMainFrame::OnViewCustomize) ON\_REGISTERED\_MESSAGE(AFX\_WM\_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew) ON\_COMMAND\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnApplicationLook) ON\_UPDATE\_COMMAND\_UI\_RANGE(ID\_VIEW\_APPLOOK\_WIN\_2000, ID\_VIEW\_APPLOOK\_WINDOWS\_7, &CMainFrame::OnUpdateApplicationLook) ON\_COMMAND(ID\_GCCODEDVMT\_TESTCOMMAND, TestCommand) //GC added 23FEB2011 ON\_COMMAND(ID\_GCCODEDVMT\_CREATEWORKERTHREAD, C
You already got answer in earlier post. If you want to pass pointer to handle, use address of m_hHandle member variable, which is handle of CMainFrame. No need to call GetSafeHwnd.
-
Many thanks for feedback :) Since posting this message I realised that I have been using the WINAPI PostMessage() function call rather than the MFC wrapper CWnd::PostMessage(). Which is the preferred method? regards Geoff
CWnd::PostMessage
internally calls win32::PostMessage
. I'll useCWnd::PostMessage
, if I'veCWnd
object(no need to wrap window handle, specially to use this version), and::PostMessage
, if I've window handle. -
Many thanks for feedback :) Since posting this message I realised that I have been using the WINAPI PostMessage() function call rather than the MFC wrapper CWnd::PostMessage(). Which is the preferred method? regards Geoff
GC104 wrote:
I have been using the WINAPI PostMessage() function call rather than the MFC wrapper CWnd::PostMessage()
You have to use the
Windows API
function. Worker threads aren'tCWnd
. :)If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles] -
CWnd::PostMessage
internally calls win32::PostMessage
. I'll useCWnd::PostMessage
, if I'veCWnd
object(no need to wrap window handle, specially to use this version), and::PostMessage
, if I've window handle.prasad_som wrote:
I'll use
CWnd::PostMessage
, if I'veCWnd
object(no need to wrap window handle, specially to use this version), and::PostMessage
, if I've window handle.So you'll use both at the same time when you have a
CWnd
object... :rolleyes: Pardon the silly humour...If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
[My articles]