Sample _beginthreadex


Click here to change the theme.

The following is a sample use of _beginthreadex. In this sample, an event is created and passed as an argument. The thread checks the event in a loop and when the event is signaled (by the main thread) the thread returns. Please read the _beginthreadex() and _endthreadex() documentation; this sample assumes you have and that you are familiar with it.

#if !defined(_MT)
#error _beginthreadex requires a multithreaded C run-time library.
#endif

#define STRICT 1
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

#define Second (1000)

unsigned __stdcall Thread(void *ArgList) {
HANDLE hEvent = *((HANDLE*)ArgList);
while (WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0) {
	Sleep(Second>>2); // sleep for a quarter of a second
	cout << "Waiting for signal\n";
	}
cout << "Thread ending\n";
return 0;
}

int main(int argc, char *argv[], char *envp[]) {
	int ErrorNumber, DOSErrorNumber;
	unsigned ThreadId;
	HANDLE hThread, hEvent;

// Create a manual-reset nonsignaled unnamed event
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

hThread = (HANDLE)_beginthreadex(NULL, 0, Thread, &hEvent, 0, &ThreadId);
if (hThread == 0) {
	ErrorNumber = errno;
	DOSErrorNumber = _doserrno;
	cerr << "Begin thread error: " << strerror(ErrorNumber) << '\n';
	cerr << "Begin thread DOS error code: " << DOSErrorNumber << '\n';
	return 16;
	}
cout << "Thread begun\n";

Sleep(Second<<1); // wait 2 seconds
SetEvent(hEvent); // signal thread to end
int rv = WaitForSingleObject(hThread, Second<<3); // wait up to 8 seconds
cout << "Thread wait rv " << rv << '\n';
CloseHandle(hEvent);
CloseHandle(hThread);

return 0;
}

Microsoft Knowledge Base article 132078 ("How to Use _beginthreadex() and _endthreadex()")

The KB article 132078 ("How to Use _beginthreadex() and _endthreadex()") seems to have been archived, so I will summarize here what it says. It essentially says that it is better to use _beginthreadex() and _endthreadex() and it has a sample program. My sample above is an improved version of the sample in the KB article.

Use of the Win32 APIs CreateThread() and EndThread() directly is incompatible with the C Runtime (CRT) Library. In particular, use of CreateThread() and EndThread() directly can cause loss of memory that the CRT allocates. Instead, we must use either _beginthread() and _endthread() or _beginthreadex() and _endthreadex().

The advantage of _beginthreadex() compared to _beginthread() is that _beginthreadex() provides more control and is safer. For example, with _beginthreadex(), you can:

  • use security information
  • create the thread suspended initially
  • get the thread identifier of the thread
  • use the thread handle after the thread completes, allowing use of the the synchronization APIs (as above) for the thread

The advantage of _endthreadex() compared to _endthread() is that _endthreadex() is more flexible.