abilash
abilash

Reputation: 897

Define thread in C++

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

Answers (3)

Steve
Steve

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

WhozCraig
WhozCraig

Reputation: 66254

Function prototype requirements for each Microsoft CRT thread launch functions are:

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

Adam Rosenfield
Adam Rosenfield

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

Related Questions