WaitForMultipleObjects() to wait threads to finish and CloseHandle() to destroy
Thread handles. [Windows thread programming example]
#include <windows.h> #include <tchar.h> #include <strsafe.h> #define MAX_THREADS 3 #define BUF_SIZE 255 DWORD WINAPI MyThreadFunction( LPVOID lpParam ); void ErrorHandler(LPTSTR lpszFunction); /* User data for threads. */ typedef struct MyData { int val1; int val2; } MYDATA, *PMYDATA; int _tmain() { PMYDATA pDataArray[MAX_THREADS]; DWORD dwThreadIdArray[MAX_THREADS]; HANDLE hThreadArray[MAX_THREADS]; // Create MAX_THREADS worker threads. for( int i=0; i<MAX_THREADS; i++ ) { pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); if( pDataArray[i] == NULL ) { ExitProcess(2); } // Set parameters to the threads. pDataArray[i]->val1 = i; pDataArray[i]->val2 = i+100; // Create thread. hThreadArray[i] = CreateThread( NULL, // default security attributes 0, // use default stack size MyThreadFunction, // thread function name pDataArray[i], // argument to thread function 0, // use default creation flags &dwThreadIdArray[i]); // returns the thread identifier if (hThreadArray[i] == NULL) { ErrorHandler(TEXT("CreateThread")); ExitProcess(3); } } // Wait for the thread to finish.
//
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
// Close all thread handles and reclaim memory.
//
for(int i=0; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
if(pDataArray[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL;
}
}
return 0;
}
// Main Thread Function.
DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
HANDLE hStdout;
PMYDATA pDataArray;
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
return 1;
// Cast the parameter to the correct data type.
// The pointer is known to be valid because
// it was checked for NULL before the thread was created.
pDataArray = (PMYDATA)lpParam;
// Print the parameter values using thread-safe functions.
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
pDataArray->val1, pDataArray->val2);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
return 0;
}
void ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}