What you tried is indeed obviously wrong, but the question is whether you understand what's wrong with it. _beginthread
takes a pointer to function (with a specific prototype and calling convention) as its first parameter.
When you write
HANDLE hThread = (HANDLE) _beginthread(ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE), 0, NULL);
you're trying to pass _beginthread
the result of calling ShellExecute
(in the current thread) which is an HINSTANCE
, while _beginthread
expects a void( __cdecl *)( void * )
(pointer to a __cdecl
function taking one void*
parameter and returning void
).
Not only your code doesn't work because you're trying to pass an HINSTANCE
where a function to pointer is expected, it doesn't make any sense. Have you read the _beginthread
documentation? There are examples there. Plural.
What you meant to write is:
HANDLE hThread = (HANDLE) _beginthread(ThreadFunc, 0, NULL);
given:
void __cdecl ThreadFunc(void*) {
ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE);
}
Or, in a more compact and easy to read form:
HANDLE hThread = (HANDLE)
_beginthread([](void*) {
ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE);
},
0, NULL);
Unless you're doing something beyong what we're seeing here, David'scomment is probably right and you should be using std::thread
or std::async
.
Also note that taking the result of _beginthread
(int contrast to the result of _beginthreadex
or CreateThread
) in unsafe because it may not be valid, as noted in the documentation. Not only that, but _beginthread
's return value isn't really a HANDLE
(it is some sore of a handle, but not a HANDLE
!), so you can't WaitForSingleObject
on it:
The _beginthreadex
function gives you more control over how the thread is created than _beginthread
does. The _endthreadex
function is also more flexible. For example, with _beginthreadex
, you can use security information, set the initial state of the thread (running or suspended), and get the thread identifier of the newly created thread. You can also use the thread handle that's returned by _beginthreadex
with the synchronization APIs, which you cannot do with _beginthread
.
It's safer to use _beginthreadex
than _beginthread
. If the thread that's generated by _beginthread
exits quickly, the handle that's returned to the caller of _beginthread
might be invalid or point to another thread. However, the handle that's returned by _beginthreadex
has to be closed by the caller of _beginthreadex
, so it is guaranteed to be a valid handle if _beginthreadex
did not return an error.
Since this thread only calls one function and exits, it almost maximizes the chance of this handle not being valid. And even if it were, you still couldn't use it to WaitForSingleObject
.