Reputation: 897
How do I start a thread using _beginthreadex()
, making it execute void myFunction(wchar_t *param);
? I try to use this:
_beginthread(NULL, 0, myFunction, L"someParam", 0, &ThreadID);
but there is compilation error:
error C2664: 'beginthreadex' : cannot convert parameter 3 from 'void (_cdecl *)(wchar_t *)' to 'unsigned int (__stdcall *)(void *)'.
How I can resolve this error? I seem able to do _beginthread((void(*)(void*))myFunction, 0 , (void *)L"someParam");
. But for _beginthreadex()
these casts don't seem to work. What do
I need to do?
This code doesn't output anything. What's wrong?
unsigned int __stdcall myFunction( void *someParam )
{
printf("Hello world!");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
_beginthreadex(NULL, 0, myFunction, L"param", 0, NULL);
return 0;
}
Upvotes: 2
Views: 1329
Reputation: 169
As in the other answer above, don't forget to wait for your thread to finish before _tmain exits, or you likely will see no output.
Upvotes: 0
Reputation: 66254
Function prototype requirements for each Microsoft CRT thread launch functions are:
_beginthread: void __cdecl procname(void * arg);
_beginthreadex: unsigned int __stdcall procname(void *arg);
You should also be aware of the differences between the two.
_beginthread: allocates a new thread and invokes the thread procedure passed as the argument. Using this API the thread-creation parameters are somewhat limited. The return value of this function is a uintptr_t, but is actually a Windows thread handle of type HANDLE. It must be cast to a HANDLE variable to be used in such functions as WaitForSingleObject
, etc. When the thread procedure finishes through normal function-exit the thread handle is automatically closed for you by the runtime. This is important. Although this function returns a thread handle just like _beginthreadex, it is conceivable for the thread to start and finish before you can do anything with the handle (such as a wait, suspend, etc.). Once the thread procedure finishes the RT will close the handle, and therefore your local variable holding the initial returned handle is now invalid.
_beginthreadex: allocates a new thread and invokes the thread procedure passed as the argument. This version allows significantly more control over how the thread is created, including the stack size, initial suspended state, etc. The return value of this function is a uintptr_t, but is actually a Windows thread handle of type HANDLE. It must be cast to a HANDLE variable to be used in such functions as WaitForSingleObject
, etc. When the thread procedure finishes through normal function-exit the thread handle is NOT automatically closed for you by the runtime. You are responsible for closing the thread handle returned by this function, and should do so as soon as it is no longer needed.
Which to use: Use _beginthread
if you have no need for the thread handle to be used in Wait functions and such, and have no special thread-creation needs (like creating a thread with an initially-suspended state). Use _beginthreadex
when you need a wait'able thread handle, finer control over the creation parameters, etc.
EDIT: Sample for the OP
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <process.h>
unsigned int __stdcall MyThread(void *p)
{
_tprintf(_T("%s\n"), p);
_tprintf(_T("Thread finishing!\n"));
return 0;
}
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, MyThread, _T("Hello, World!"), 0, NULL);
if (hThread != INVALID_HANDLE_VALUE)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
_tprintf(_T("Thread finished!\n"));
}
return 0;
}
Upvotes: 4
Reputation: 400642
_beginthreadex
requires a function that uses the __stdcall
calling convention, not the __cdecl
calling convention, which is the default. To fix it, declare your thread procedure with the __stdcall
calling convention:
unsigned int __stdcall myFunction(void *arg)
{
...
}
Do NOT cast the function pointer you're passing into _beginthread
or _beginthreadex
: a function pointer cast is a bug waiting to happen.
Upvotes: 5