INTRODUCTION AND RELEVANT INFORMATION:
I have a main window with a button.
On button click a dialog box is shown.
Dialog box has a button that spawns a thread.
Thread function communicates with the dialog box via 2
custom messages
.
Right now I am using a
boolean
variable the way it was used in the thread example from book
Programming Windows, 5th edition-Charles Petzold.
I wish to improve the code for thread synchronization, namely to substitute the usage of boolean
and global variables for something more efficient.
The important information is also the way threads are aborted when user presses
Alt+F4
or
X button
on either dialog box or main window so here is the explanation of the algorithm I have deployed:
If the user tries to close the main window while thread is still running, I set the global
boolean
variable and leave
WM_CLOSE
handler without destroying the window. I also send
WM_CLOSE
to the dialog box.
In the dialog procedure, in
WM_CLOSE
handler, I check if thread is still running and if it does I send abort signal and return without destroying the dialog box.
Now both main window and dialog box are alive and wait for thread to finish.
Once thread sends
custom message
, informing the dialog box it has finished, I check the global
boolean
variable and if it is set I post the
WM_CLOSE
to the main window and I post
WM_CLOSE
to the dialog box if the user requested to close it.
Close request for dialog box is stored in a
boolean
variable that gets set when user tries to close dialog box.
As far as thread function is concerned, I check the value of
bContinue
periodically and abort thread properly when it is set to
false
.
Here are the relevant code snippets:
struct Data
{
bool bContinue; };
static bool g_closeApp;
The main window's WM_CLOSE handler:
case WM_CLOSE:
closeApp = true;
if( IsWindow( hDlgTSO ) )
{
SendMessage( hDlgTSO, WM_CLOSE, 0, 0 );
return (LRESULT)0; }
return (LRESULT)0;
The relevant dialog box snippets:
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
static HANDLE threadHandle;
static Data data; static bool closeDlg;
switch(Message)
{
case WM_INITDIALOG:
{
closeDlg = false;
threadHandle = NULL;
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDOK:
{
DWORD threadID;
data.bContinue = true;
threadHandle = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)ThreadFunction,
(void*)&data, 0, &threadID );
if( !threadHandle )
{
MessageBox( hwnd, L"Error!", L"Error", MB_ICONERROR );
DestroyWindow(hwnd); }
}
break;
}
break;
case WM_CLOSE:
closeDlg = true; if( threadHandle ) {
ShowWindow( hwnd, SW_HIDE );
data.bContinue = false;
}
else
{
if( closeApp ) PostMessage( GetParent( hwnd ), WM_CLOSE, 0, 0 );
threadHandle = NULL;
DestroyWindow(hwnd);
hDlgTSO = NULL; }
return TRUE;
case WM_THREAD_OK: if( threadHandle ) {
WaitForSingleObject( threadHandle, INFINITE );
CloseHandle( threadHandle );
threadHandle = NULL;
}
if( closeDlg )
PostMessage( hwnd, WM_CLOSE, 0, 0 );
return TRUE;
default:
return FALSE;
}
return TRUE;
}
The thread function:
DWORD WINAPI ThreadFunction( LPVOID pvoid )
{
volatile Data* data = ( Data* )pvoid;
if( ! data.bContinue ) }
MY QUESTION:
Is there a better implementation which would enable me to remove
boolean
variables,
especially the global one?
I do not seek suggestion for synchronization mechanism as I believe that current one is OK, but if anyone has better suggestion I will consider it.
Thank you.
Best regards.