Then you have to use an event as I described in the last few sentences. If you are not familiar with that then this description will help a lot, otherwise just ignore it. :)
Put an event object somewhere in your app class as a member
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
Exactly after
mMyDialog.m_bCancel = TRUE;
when you press the cancel button wait for this event to become signaled:
WaitForSingleObject(hEvent, INFINITE);
You can replace INFINITE to some timeout if your worker thread is not safe and may hang forever. In this case it is good practice to call
TerminateThread()
after the timeout, but don't do this timeout/terminate thing if your worker thread 100% stops working when you set the cancel flag. In your worker thread after releasing your resources you should signal the event to tell the main thread so that it can continue execution (maybe do the program exit):
SetEvent(hEvent);
Don't put this into your
func()
, because the vector is on the stack and the function has to return in order to release the vector. If you singal the event inside
func()
then the main thread may terminate the prog before
func()
can cleanup gracefully. Instead put the event signaling after the call of
func()
when it is 100% sure that there are no releasable resources left, all what we have to do is exiting the thread:
while (!pApp->mMyDialog.m_bCancel)
pApp->func();
SetEvent(hEvent);
Don't forget to delete the event handle in the destructor of your class with
CloseHandle()
. If you want to use this event more than once for more operations then at the beginning of the operation don't forget to reset it with
ResetEvent()
.
One more thing, because it doesn't take much time copy-pasting, Its always a good practice to encapsulate an API handle and the related API functions into a class/struct like the following: (you can use this wherever you would otherwise use a
HANDLE
that must be closed with
CloseHandle()
(for example your event object), and this often saves you from leaking a handle. Have fun!!! :)
struct SWinHandle
{
SWinHandle(HANDLE _handle=NULL)
: handle(_handle)
{
}
SWinHandle(SWinHandle& other)
: handle(other)
{
other.handle = NULL;
}
~SWinHandle()
{
Close();
}
void Close()
{
if (handle!=NULL && handle!=INVALID_HANDLE_VALUE)
{
::CloseHandle(handle);
handle = NULL;
}
}
operator HANDLE() const
{
return handle;
}
HANDLE Release()
{
HANDLE h = handle;
handle = NULL;
return h;
}
SWinHandle& operator=(HANDLE _handle)
{
Close();
handle = _handle;
return *this;
}
SWinHandle& operator=(SWinHandle& other)
{
Close();
handle = other;
other.handle = NULL;
return *this;
}
HANDLE handle;
};