Creating a New Thread

Now that we can synchronize threads, we need to be able to create them. Several families of functions create, manage, and end a thread in a program. Before deciding which family of functions to use, you need to determine exactly what kind of program you plan to write, as well as how many threads you plan to create.

Thread Creation Functions

For a pure Win32 application that does not use any C run-time library functions, the CreateThread and ExitThread functions can be used to create and end, respectively, a thread.

 HANDLECreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes, DWORDdwStackSize,LPTHREAD_START_ROUTINElpStartAddress, LPVOIDlpParameter,DWORDdwCreationFlags,LPDWORDlpThreadId); VOIDExitThread(DWORDdwExitCode); 

You should not need to explicitly call ExitThread since it is called whenever a thread created by CreateThread returns, but some of the documentation from Microsoft recommends that ExitThread be called explicitly where possible.

You won't use these functions if you are using functions in the C run-time library or if you are using MFC. Use of MFC is beyond the scope of this discussion, but issues related to use of the C run-time library could be significant in the context of server development.

Some standard C run-time library functions (for instance, malloc, fopen ) cause allocation of a C run-time library per-thread data block. The CreateThread/ExitThread pair do not properly free this block if allocated, and the possibility exists of a memory leak of about 70-80 bytes for each thread terminated with ExitThread that uses C run-time library functions. Recall from the Chapter 1 discussion of the Microsoft bug report related to ASP.DLL that even very minor memory leaks can create problems in long-running services. Note that the general perception is that C run-time library functions will not work at all if CreateThread is used rather than the C run-time library _beginthreadex function. In reality, according to Microsoft Knowledge Base article ID Q104641, the only function that cannot be used in a thread created by CreateThread is the signal function.

The alternative for threads that must use the C run-time library functions is a pair of functions named _beginthreadex and _endthreadex .

 HANDLE_beginthreadex(void*lpThreadAttributes, unsigneddwStackSize, unsigned(__stdcall*start_address)(void*)lpStartAddress, void*arglist,unsignedinitFlag,unsigned*thrdaddr); VOID_endthreadex(unsignedretval); 

Another family of thread creation/termination functions is beginthread/endthread . These functions are less like the standard Win32 counterparts; the most significant difference is that beginthread does not take a security attributes parameter. The similarity of function parameters will make it easier to switch from one thread creation family to another, so we will use the beginthreadex/_endthreadex functions when C run-time library support is required.

NOTE
For multithreaded projects, be sure you change the code generation options in the Project Settings dialog box to use the multithreaded C run-time library.

After discussing the basics of multithreaded applications, let's take a look at a rather contrived example that will allow us to see threads in action. As with all examples in the book, this example is also on the companion CD.

A Multithreaded Example Program

This example program is simple: it creates five threads from the primary thread in a simple 32-bit console-mode application. Console-mode applications will be discussed in more detail later in this book, but for now, just think of them as simple 32-bit programs that allow use of Win32's full range of functionality. Each of the five threads waits indefinitely for ownership of a mutex created in the main function before the threads are created. When a thread gains ownership of the mutex, it holds the mutex for some period of time and then releases it. Each thread monitors a global variable, synchronized by a critical section, to determine whether it should terminate. The global variable is set when the user presses a key. We will use the _ beginthreadex/_endthreadex pair since we are using standard C run-time library functions. The code is in Listing 2-1.

Listing 2-1

Thread Creation and Thread Synchronization Functions

 #include<stdio.h> #include<conio.h> #include<windows.h> #include<process.h> CRITICAL_SECTIONcsExit; BOOLexitNow=FALSE; HANDLEhMutex; unsigned__stdcallSecondThreadFunc(void*pArguments); intmain(intargc,char*argv[]); unsigned__stdcallSecondThreadFunc(void*pArguments) { intthreadNum; threadNum=*((int*)pArguments); printf("Inthread%d...\n",threadNum); while(TRUE) { WaitForSingleObject(hMutex,INFINITE); Sleep(1000*threadNum); EnterCriticalSection(&csExit); if(exitNow) { printf("\nThread%dGONE!",threadNum); _endthreadex(0); } LeaveCriticalSection(&csExit); ReleaseMutex(hMutex); printf("\nThread%dstillgoing",threadNum); } return0; } intmain(intargc,char*argv[]) { intloop; intthreadCount[5]; unsignedthreadID[5]; InitializeCriticalSection(&csExit); __try { for(loop=0;loop<5;loop++) { threadCount[loop]=loop+1; _beginthreadex(NULL, 0, &SecondThreadFunc, &threadCount[loop], 0, &threadID[loop]); } getch(); EnterCriticalSection(&csExit); exitNow=TRUE; LeaveCriticalSection(&csExit); } __finally { DeleteCriticalSection(&csExit); } return0; } 

When the program is run, it gives you feedback as each thread is started and as each thread is testing for the exitNow flag to be set, and it reports whether it is still running. You will notice that when you run this program, the performance is a bit choppy. That is something that you may find in many multithreaded applications. The synchronization objects that have been discussed and used in this example are useful for their intended purpose, but if there is a reasonable alternative, you should be careful to avoid using resources that need to be shared. Wherever possible, try to use constructs that allow server clients to operate without interactions with other clients, such as requiring waits for availability of shared resources.



Inside Server-Based Applications
Inside Server-Based Applications (DV-MPS General)
ISBN: 1572318171
EAN: 2147483647
Year: 1999
Pages: 91

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net