I have a DLL which has a CWinThread based class called CWork.
I create it using AfxBeginThread.
In this class I defined a procedure that will loop infinetly and perform a certain task. This procedure will be used as a thread by itself. I create it also using AfxBeginThread.
Now, when my DLL exits, I'd like to end the thread. This is because I have a crash on exit, and I am affraid that is the reason.
In addition, there is
Pseudo Code example:
class Cmain
Cmain::Cmain(){
pMyThread = AfxBeginThread(CWork - a CWinThread based Class);
}
UINT HandleNextVTSConnectionCommandProc(LPVOID pParam);
class CWork
CWork:CWork(){
AfxBeginThread(HandleNextVTSConnectionCommandProc, this);
}
UINT HandleNextVTSConnectionCommandProc(LPVOID pParam){
while(true){
dosomething();
sleep(2000);
}
}
My question is, what is the correct way of ending those 2 threads?
Thank you!
In general the correct way to end a thread is to ask it to finish and then wait for it to do so. So on Windows you might signal an event to ask the thread to finish up then wait on the thread HANDLE. Forcefully terminating a thread is almost always a misguided idea which will come back to haunt you.
Create an event calling CreateEvent that is initially non-signaled. When your application terminates, signal this event (SetEvent) and wait for the thread to terminate (WaitForSingleObject on the thread handle).
Inside your thread function HandleNextVTSConnectionCommandProc replace your while(true) loop with
while(WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
Doing the above allows you to signal the thread to terminate from your application. The thread terminates, when it returns from its thread proc.
Set a flag instead of using while(true) to tell your thread when it should end. You could also use an event.
You should also wait for your thread to be complete before you exit, so you should use (in the main code, once you signal the thread to end):
WaitForSingleObject(thread_handle)
Something like this should get you started:
HANDLE g_hThreadExitRequest = NULL;
UINT __cdecl ThreadFunction(LPVOID pParam)
{
AllocConsole();
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
for (int i=1; true; ++i)
{
CStringA count;
count.Format("%d\n", i);
WriteFile(hCon, (LPCSTR)count, count.GetLength(), NULL, NULL);
if (WaitForSingleObject(g_hThreadExitRequest, 1000) == WAIT_OBJECT_0)
break;
}
// We can do any thread specific cleanup here.
FreeConsole();
return 0;
}
void Go()
{
// Create the event we use the request the thread exit.
g_hThreadExitRequest = CreateEvent(
NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
TRUE, // BOOL bManualReset
FALSE, // BOOL bInitialState
NULL // LPCTSTR lpName
);
// We create the thread suspended so we can mess with the returned CWinThread without
// MFC auto deleting it when the thread finishes.
CWinThread *pThread = AfxBeginThread(
&ThreadFunction, // AFX_THREADPROC pfnThreadProc
NULL, // LPVOID pParam
THREAD_PRIORITY_NORMAL, // int nPriority
0, // UINT nStackSize
CREATE_SUSPENDED , // DWORD dwCreateFlags
NULL // LPSECURITY_ATTRIBUTES lpSecurityAttrs
);
// Turn off MFC's auto delete "feature".
pThread->m_bAutoDelete = FALSE;
// Start the thread running.
pThread->ResumeThread();
// Wait 30 seconds.
Sleep(30*1000);
// Signal the thread to exit and wait for it to do so.
SetEvent(g_hThreadExitRequest);
WaitForSingleObject(pThread->m_hThread, INFINITE);
// Delete the CWinTread object since we turned off auto delete.
delete pThread;
// We're finished with the event.
CloseHandle(g_hThreadExitRequest);
g_hThreadExitRequest = NULL;
}
Related
My application has a separate thread that repeatably performs some check. If the check fails, the UI thread is notified (a MessageBox is displayed that requires user action what to do next).
Unfortunately, I have to use C++03 compiler (Visual Studio 2010 SP1) and boost library usage is prohibited. Therefore, I cannot use <thread>, <atomic>, <chrono>, etc. Thats why I have to use CreateThread, PostMessage and other WinAPI functions.
Here is my UI thread code (simplified). My main window is CMDIFrameWnd (from MFC):
//a struct with all parameters that is needed for a repeatable check
struct RepeatFunctionParameters
{
unsigned int repeatDelayInMilliseconds;
HWND checkIsFailedPostMessageWindowHandler;
UINT checkIsFailedPostMessageMessageId;
HANDLE checkIsPausedMutexHandle;
RepeatFunctionParameters(unsigned int _repeatDelayInMilliseconds, HWND _checkIsFailedPostMessageWindowHandler,
UINT _checkIsFailedPostMessageMessageId, HANDLE _haspSerialCheckIsPausedMutexHandle)
: repeatDelayInMilliseconds(_repeatDelayInMilliseconds), checkIsFailedPostMessageWindowHandler(_checkIsFailedPostMessageWindowHandler),
checkIsFailedPostMessageMessageId(_checkIsFailedPostMessageMessageId), haspSerialCheckIsPausedMutexHandle(_haspSerialCheckIsPausedMutexHandle)
{}
};
----------------------------
//creating a mutex to pause repeatable checks (whe Messagebox is displayed in UI thread)
HANDLE haspSerialCheckIsPausedMutexHandle = CreateMutex(NULL, FALSE, NULL);
//starting a separate thread with a check that repeats every 5000 milliseconds
auto params = new RepeatFunctionParameters(5000, myApp_hWnd, WM_USER_HASP_CHECK_FAILED, haspSerialCheckIsPausedMutexHandle);
CreateThread(NULL, 0, RepeatFunction, params, 0, NULL);
----------------------------
//special message that is sended when check is failed
#define WM_USER_HASP_CHECK_FAILED (WM_USER+0x150)
//mapping message handling function to that message
ON_MESSAGE( WM_USER_HASP_CHECK_FAILED, OnUserHaspCheckFailed)
//message handling function definition
afx_msg LRESULT OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam);
//message handling function body
LRESULT CMainWnd::OnUserHaspCheckFailed(WPARAM wParam, LPARAM lParam)
{
//capturing a mutex that signals to pause repeatable checks
WaitForSingleObject(haspSerialCheckIsPausedMutexHandle, INFINITE);
//show a messagebox that requires user action what to do next
if (::MessageBox(myApp_hWnd, ("Check is failed! Retry or cancel?").c_str(),
myApp_name, MB_RETRYCANCEL | MB_ICONERROR | MB_SYSTEMMODAL) == IDCANCEL)
//closing main windows if user clicks Cancel
pWnd->SendMessage(WM_CLOSE, 0x00010000, 0);
//releasing a mutex that signals to pause repeatable checks
ReleaseMutex(haspSerialCheckIsPausedMutexHandle);
return 0;
}
//WM_CLOSE handling function body
LRESULT CMainWnd::OnClose( WPARAM wParam, LPARAM lParam)
{
----------------------------
if( haspSerialCheckIsPausedMutexHandle != NULL)
CloseHandle( haspSerialCheckIsPausedMutexHandle);
----------------------------
CMDIFrameWnd::OnClose();
return NULL;
}
Here is my separate thread with repeatable check code (simplified):
DWORD WINAPI RepeatFunction(LPVOID parameters)
{
//getting parameters struct from a pointer
auto temp = static_cast<RepeatFunctionParameters*>(parameters);
//make a struct local copy (Further, all work goes only with it, regardless of the
state of the object, the pointer to which came as a function parameter)
auto params = *temp;
//deleting the structure, the pointer to which came as a function parameter
delete temp;
//repeatable check
while (true)
{
//checking a mutex that signals to pause repeatable checks. if it is free
//then there is no messagebox in UI thread and we can perform a check.
//if it is captured - wait until user clicks some button in that messagebox
WaitForSingleObject(params.haspSerialCheckIsPausedMutexHandle, INFINITE);
//and releasing it immediately
ReleaseMutex(params.haspSerialCheckIsPausedMutexHandle);
auto startMilliseconds = GetTickCount();
//performing a check
BOOL success = PerformACheck();
unsigned long defaultSleepDelay = 1000;
//if PerformACheck() will last longer than params.repeatDelayInMilliseconds,
//then check will be repeated after 1000 milliseconds, otherwise -
//after params.repeatDelayInMilliseconds minus PerformACheck() call time
auto endMilliseconds = GetTickCount();
if ((endMilliseconds - startMilliseconds) < params.repeatDelayInMilliseconds)
sleepDelay = params.repeatDelayInMilliseconds - (endMilliseconds - startMilliseconds);
//if check is failed
if (!success)
{
//sending a message with an identifier params.checkIsFailedPostMessageMessageId
//to a HWND params.checkIsFailedPostMessageWindowHandler so in it's
//handling function a messagebox with will be displayed and a mutex
//params.haspSerialCheckCanRunMutexHandle will be captured until
//user click some button in that messagebox
PostMessage(params.checkIsFailedPostMessageWindowHandler, params.checkIsFailedPostMessageMessageId, 0, 0);
//if check is failed then next check always repeats after 1000 milliseconds
sleepDelay = 1000;
}
Sleep(sleepDelay);
}
}
The result is that the main window becomes unresponsive after some time. It looks like my code has some logical mistake, or a memory leak.
I'm a newbie to C++ (and especially to outdated standards).
I have read that I need to have the HWND placed on the heap. Is that correct?
I need this to read values from user input.
Thank you in advance!
VOID MakeThread(HWND hWnd)
{
HWND* h = new HWND(hWnd);
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, h, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
delete h;
}
unsigned int __stdcall WorkerThread(VOID* h)
{
char num[71] = { 0 };
GetDlgItemTextA((*(HWND*)h), 2001, num, 70);
//Get number from edit box 2001
//Do work with the above-mentioned number
return 0;
}
I have read that I need to have the HWND placed on the heap. Is that correct?
Not really. Assuming that the HWND remains valid for the duration of the created thread (if it is the application's main window, then that is a reasonable assumption), and that the MakeThread function will not return until that thread is finished (as is the case in your code), then you can just give the address of its HWND hWnd argument as the arglist parameter in the call to _beginthreadex.
You don't have to create a copy of that window handle on the heap. Here's a simplified version of your MakeThread function:
VOID MakeThread(HWND hWnd)
{
stringstream stream;
stream << &hWnd << "\n" << hWnd;
std::string s = stream.str();
MessageBoxA(hWnd, s.c_str(), "Caller: hWnd?", 0);
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, &hWnd, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
}
However, if your MakeThread function were to return without waiting for the created thread to complete, then that passed address would become invalid (at some point). But, in that scenario, you would have to make other changes to your code, so that you could keep track of the created thread handle.
An HWND is already a pointer type (to a global system resource). You can just pass it around as-is, there is no need to wrap it with new at all:
void MakeThread(HWND hWnd)
{
HANDLE hThread = (HANDLE)_beginthreadex(nullptr, 0, WorkerThread, hWnd, 0, nullptr);
if (hThread != nullptr) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
}
unsigned int __stdcall WorkerThread(void* h)
{
char num[71] = { 0 };
GetDlgItemTextA((HWND)h, 2001, num, 70);
//Get number from edit box 2001
//Do work with the above-mentioned number
return 0;
}
That being said, creating a thread just to immediately wait for its termination is a complete waste of a thread. You may as well just call the target function directly instead, the end result will be exactly the same, just without the extra overhead:
void DontMakeThread(HWND hWnd)
{
WorkerThread(hWnd);
}
As soon as you use new HWND(hWnd), your object will be allocated on the heap by default, not stack. Thus, you can share it across without a risk the object to be lost due the stack unwinding.
Another point is you start the thread and then wait for the completion. As a side-effect, you could use even a stack-allocated data to pass to the thread because the stack is here until the thread exit (exactly, WaitForSingleObject line).
And handling user input is not related to heap/stack allocation in general. Could you re-phrase your question in that part or create another question on that mean?
I have set an int variable for the "EditBox" control in c++/mfc. now I want to change its value in a thread.
I define a thread like the bellow :
CWinThread *pThread();
UINT FunctionThread(CthDlg& d)
{
DWORD result = 0;
int i = 0;
while (1)
{
if (i == 5000) i = 0;
d.m_text1 = i;
i++;
d.UpdateData(FALSE);
}
return result;
}
void CthDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
pThread = AfxBeginThread(FunctionThread, THREAD_PRIORITY_NORMAL);
}
Where's the Problem?
You should run your code in debug mode and under the debugger, then you would see that you get an assertion.
The problem is that MFC only allows access to a window from the thread that created the window. In your case that means that the main thread can access the windows, but the worker thread can not. UpdateData is accessing the windows, so this does not work in a worker thread.
So what you need to do is signal from the worker thread to the main thread that a new value is available and shall be displayed. For that signaling you can post a window message to the dialog window (PostMessage). Be sure not to use SendMessage because this will block until the message is received. You might run into a dead lock if the main thread is waiting for the worker thread and the worker thread is waiting for the main thread in SendMessage. When the main thread receives the message it can update the window control.
BTW, your code is not valid. AfxBeginThread requires a AFX_THREADPROC which is declared as UINT __cdecl MyControllingFunction(LPVOID pParam);. You need to change your thread function to
UINT __cdecl FunctionThread(LPVOID pParam)
{
CthDlg& d = *reinterpret_cast<CthDlg*>(pParam);
I have a thread that does lengthy processing. While I am waiting for the thread to finish, I kick start another 'show progress' thread which simply toggles a bitmap back and forth to show program is crunching on data. To my surprise this approached didn't work at all.
My 'show progerss' thread simply stop updating (=running) when the main activity starts and it starts updating when that activity ends. This is nearly the oppose of what I want! Should I expect this behavior because of the WaitForSingleOBjectwhich is in wait state for most of the time and wakes up briefly?
// This is the main thread that does the actual work
CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();
// before I start to wait on the above thread, I start this thread which will toggle image to show application is processing
AfxBeginThread(ProgressUpdateThread, &thread_struct_param, THREAD_PRIORITY_NORMAL, 0 );
// wait for the main thread now.
DWORD dwWaitResult = WaitForSingleObject( thread->m_hThread, INFINITE );
DWORD exitCode;
::GetExitCodeThread( thread->m_hThread, &exitCode );
delete thread;
// This thread toggles image to show activity
UINT ProgressUpdateThread(LPVOID param)
{
CEvent * exitEvent = ((mystruct *)param)->exitEvent;
MyView *view ((mystruct *)param)->view;
int picture = 0;
do
{
waitResult = WaitForSingleObject( exitEvent->m_hObject, 100);
if (waitResult == WAIT_TIMEOUT)
{
picture = toggle ? 1: 0;
// invert
toggle = !toggle;
View->Notify( UPDATE_IMAGE, picture );
}
else if (waitResult == WAIT_OBJECT_0)
{
return TRUE;
}
}
while( 1);
}
Another consideration in my solution is that I would like to not touch the actual 'DoWork' thread code and that's also why I am using separate thread to update GUI. Can I make this approach work? Is the only way to update GUI reliable is to update it from the actual 'DoWork thread itself?
I do want to clarify that my 'Show progress' thread does the job perfectly if the application is idle, but if I launch the worker thread operation (in lower thread priority), the update gui thread simply stops running and resume only when the worker finishes.
I am using Windows 7.
Your design is all wrong and over-complicated for what you are attempting. Try something more like this simpler solution:
bool toggle = false;
VOID CALLBACK updateProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
int picture = toggle ? 1: 0;
toggle = !toggle;
View->Notify( UPDATE_IMAGE, picture );
}
CWinThread* thread = AfxBeginThread(threadDoWork, this, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED );
thread->m_bAutoDelete = FALSE;
thread->ResumeThread();
UINT_PTR updateTimer = SetTimer(NULL, 0, 100, updateProc);
do
{
DWORD dwWaitResult = MsgWaitForMultipleObjects(1, &(thread->m_hThread), FALSE, INFINITE, QS_ALLINPUT );
if (dwWaitResult == WAIT_OBJECT_0)
break;
if (dwWaitResult == (WAIT_OBJECT_0+1))
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
while (true);
KillTimer(NULL, updateTimer);
DWORD exitCode;
::GetExitCodeThread( thread->m_hThread, &exitCode );
delete thread;
If you do not want to use a standalone procedure for the timer, you can adjust the parameters of SetTimer() to have it post WM_TIMER messages to an HWND of your choosing instead, and then do the UI updates in that window's message procedure as needed. You would still need the message loop to pump the timer messages, though.
The alternative is to simply not do any waiting at all. Once you start the worker thread, move on to other things, and let the worker thread notify the main UI thread when it is done with its work.
Remy Lebeau pointed out correctly that my main GUI thread was actually waiting on the worker thread. Now since my worker gui-update thread was (obviously) calling gui function, it was in turn blocked on main GUI thread. I realized even SetWindowText() from a third thread will put that thread in wait if the main GUI thread is in wait or blocked state.
I don't like to use PeekandPump() mechanism, I thought it was a bad design smell. It was originally used in early windows (before win95 I think) which were not truly multitasking. To the best of my knowledge this should not be used now.
My solution was to put the whole code that I posted in OP in a new thread. So my button click in gui creates this threat and returns immediately. This master worker thread can now wait on other threads and my GUI will never block. When it gets completed, it post a message to the parent window to notify it. The bitmap is now changed perfectly using a separate gui-update thread when the application is processing in another thread.
I think i am ruining in to a deadlock, have been searching for the solution over hours. Any suggestions?
What i am trying to do is: ater startGame button click, create thread that send request to the server and then gets the answer, after the answer the thread must send a message to Initialize game window to the main proc...
Message Proc that belongs to WinMain:
LRESULT CALLBACK WndProc(HWND myWindow, UINT messg, WPARAM wParam, LPARAM lParam)
{
switch (messg) {
case WM_STARTGAME:
DestroyWindow(hStartGameButton);
DestroyWindow(hHistoryButton);
InitGameWindow(myWindow);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_STARTGAME_BUTTON:
{
parametros param;
param.myWindow = myWindow;
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
}
}
}
And this is the thread:
DWORD WINAPI ThreadStartGame(LPVOID param){
HWND w = (HWND)param;
DWORD n;
BOOL ret;
mensagem resposta;
mensagem msg;
msg.tipo = COMECAR_JOGO;
msg.verifica = true;
if (!WriteFile(hPipe, &msg, (DWORD)sizeof(mensagem), &n, NULL)) {return 0;}
ret = ReadFile(hPipeN, &resposta, (DWORD)sizeof(mensagem), &n, NULL);
if (!ret || !n) {
return false;
}
PostMessage(w, WM_STARTGAME, NULL, NULL); // <- THIS GETS EXECUTED BUT NOTHINK HAPPENS AFTER
return 0;
}
I don't think there is any deadlock here.
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)&myWindow, 0, NULL);
This line passes the address of the HWND to the thread (&myWindow)
HWND w = (HWND)param;
This line uses the adress itself as HWND and the SendMessage sends the message to this address which is not a HWND.
Try modifying to
start_game = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadStartGame, (LPVOID)myWindow, 0, NULL);
W/o even looking at the code, I can tell you right away: do not use SendMessage between threads. I recommend reading Psychic debugging: The first step in diagnosing a deadlock is a simple matter of following the money and Preventing Hangs in Windows Applications:
Use asynchronous window message APIs in your UI thread, especially by replacing SendMessage with one of its non-blocking peers: PostMessage, SendNotifyMessage, or SendMessageCallback
...
Any blocking call that crosses thread boundaries has synchronization properties that can result in a deadlock. The calling thread performs an operation with 'acquire' semantics and cannot unblock until the target thread 'releases' that call. Quite a few User32 functions (for example SendMessage), as well as many blocking COM calls fall into this category.
For starters, you're unlikely supposed to do that in the first place. Quoting MSDN:
A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.
Second, your thread can be worker or UI thread, from the first type you must not call most of the window related functions, as it has no message pump. DestroyWindow is such. (So many times I tried to use MessageBox despite my own comment a few lines upper telling it's forbidden in that function ;).
From worker threads the usual method is to use PostThreadMessage and react on the UI thread. (If you have multiple UI threads, I don't know the rules, was never brave enough for that.)