Terminating
Threads
Although there are multiple ways to cause a thread to terminate, the
recommended approach is for the thread to exit the function that it was
instructed to run. In Listing 6.6, the thread will print out its ID and then
exit.
Listing 6.6 Printing
Thread ID and Exiting
DWORD WINAPI mythread( __in LPVOID lpParameter )
{
printf( "Thread %i \n", GetCurrentThreadId() ); return 0;
}
It is also possible to cause threads to terminate
using the call ExitThread() or TerminateThread(). However, these are not recommended because they may leave the
application in an unspecified state. The thread
does not get the opportunity to release any held mutexes or free any other
allocated resources. They also do not give the run-time libraries the
opportunity to clean up any resources that they have allocated on behalf of the
thread.
As long as care is taken to ensure that resources
the thread has acquired are appropri-ately freed, a thread may terminate with a
call to _endthread() or _endthreadex(). This call needs to match the call that was used to create the thread.
If the thread exits with a call to _endthreadex(), the handle to the thread still needs to be closed by another thread calling
closeHandle().
In a fork-join type model, there will be a master
thread that creates multiple worker threads and then waits for the worker
threads to exit. There are two routines that the master thread can use to wait
for the worker to complete: WaitForSingleObject() or WaitForMultipleObjects(). As indicated by their names, these two routines will wait
either for the completion of a single thread or for
the completion of an array of threads. The routines take the handle of the
thread as a parameter together with a timeout value that indicates how long the
master thread should wait for the worker thread to com-plete; usually the value
INFINITE will be
appropriate. Listing 6.7 shows the code neces-sary to wait for a single thread
to complete.
Listing 6.7 Using
WaitForSingleObject()
#include <windows.h> #include
<process.h>
unsigned
int __stdcall mywork( void * data )
{
printf( "Thread %i\n", GetCurrentThreadId() ); return 0;
}
int
_tmain( int argc, _TCHAR* argv[] )
{
HANDLE h[2];
for (int i=0; i<2; i++)
{
h[i] = (HANDLE)_beginthreadex( 0, 0, &mywork, 0, 0, 0 );
}
for (int i=0; i<2; i++)
{
WaitForSingleObject(
h[i], INFINITE );
CloseHandle( h[i] );
}
getchar();
}
Listing 6.8 shows the equivalent code using WaitForMultipleObjects(). The first parameter to the function call is the number of threads that
are to be waited for. The second parameter is a pointer to the array of handles
to these threads. The third parame-ter is a boolean that, if true, indicates that the function should return when all the threads are
complete or, if false,
indicates the function should return on the comple-tion of the first worker
thread. The final parameter is the length of time that the master thread should
wait before returning anyway. Listing 6.8 shows an example of calling this.
Listing 6.8 Using
WaitForMultipleObjects()
int _tmain( int argc, _TCHAR* argv[] )
{
HANDLE h[2];
for (int i=0; i<2; i++)
{
h[i] = (HANDLE)_beginthreadex( 0, 0, &mywork, 0, 0, 0 );
}
WaitForMultipleObjects(
2, h, true, INFINITE );
for (int i=0; i<2; i++)
{
CloseHandle( h[i] );
}
getchar();
}
Even after a thread created by a call to _beginthreadex() has exited, it will con-tinue to hold resources. These resources need
to be freed by calling the CloseHandle() function
on the handle to the thread. Listing 6.9 shows the complete sequence of
creat-ing a thread, waiting for it to complete, and then freeing its resources.
Listing 6.9 Complete
Thread Life Cycle
int _tmain( int argc, TCHAR* argv[] )
{
HANDLE handle;
handle =
(HANDLE)_beginthreadex( 0, 0, &routine, 0, 0, 0 );
returnvalue =
WaitForSingleObject( handle, INFINITE );
CloseHandle(
handle );
return 0;
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.