Reputation: 79
I need to run for example:
ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE);
as new thread, but I don't know how. I tried this:
HANDLE hThread = (HANDLE) _beginthread(ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE), 0, NULL);
WaitForSingleObject( hThread, INFINITE );
but obviously it's wrong and can't be compiled. How should I do this?
Upvotes: 0
Views: 853
Reputation: 3718
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
.
Upvotes: 3