Search code examples
c++multithreadingwinapibeginthreadex

passing PVOID array, containing multiple type variables to _beginthreadex()


I want to pass an HANDLE and a HWND variables to a _beginthreadex function, I don't want to set those variable global.

that's what i've tried :

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR 
lpCmdLine, int nShowCmd)
{
    HANDLE t = NULL;
    HWND wnd = NULL;

    // initialization of wnd and t by their functions

   PVOID args[2];
   args[0] = &t;
   args[1] = &wnd;

   _beginthreadex(NULL, 0, threadfunc, args, NULL,NULL,NULL);

   // doing some additional stuff
   return 0;
} 

unsigned int __stdcall threadfunc(PVOID args){
    waitforsingleobject(*(PHANDLE)args[0], INFINITE);
    EnableWindow((PHWND)args[1]) ;
    return 0;
}

this unfortunately does'nt work.. an ideas?


Solution

  • It doesn't work because you are not type-casting args correctly. You would need something more like this instead:

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR 
    lpCmdLine, int nShowCmd)
    {
        HANDLE t = NULL;
        HWND wnd = NULL;
    
        // initialization of wnd and t by their functions
    
        void* args[2];
        args[0] = &t;
        args[1] = &wnd;
    
        _beginthreadex(NULL, 0, threadfunc, args, NULL, NULL, NULL);
    
        // doing some additional stuff
        // make sure args, t and wnd don't go out of scope before the thread terminates...
    
        return 0;
    } 
    
    unsigned int __stdcall threadfunc(PVOID args)
    {
        void **pargs = (void**) args;
        HANDLE t = * (HANDLE*) pargs[0];
        HWND wnd = * (HWND*) pargs[1];
    
        WaitForSingleObject(t, INFINITE);
        EnableWindow(wnd, TRUE);
    
        return 0;
    }
    

    Or, using dynamic allocation:

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR 
    lpCmdLine, int nShowCmd)
    {
        HANDLE t = NULL;
        HWND wnd = NULL;
    
        // initialization of wnd and t by their functions
    
        void **args = new void*[2];
        args[0] = &t;
        args[1] = &wnd;
    
        if (!_beginthreadex(NULL, 0, threadfunc, args, NULL, NULL, NULL))
            delete[] args;
    
        // doing some additional stuff
        // make sure t and wnd don't go out of scope before the thread terminates...
    
        return 0;
    } 
    
    unsigned int __stdcall threadfunc(PVOID args)
    {
        void **pargs = (void**) args;
        HANDLE t = * (HANDLE*) pargs[0];
        HWND wnd = * (HWND*) pargs[1];
    
        WaitForSingleObject(t, INFINITE);
        EnableWindow(wnd, TRUE);
    
        delete[] pargs;
        return 0;
    }
    

    A better solution is to use a struct instead of an array:

    struct MyHandles
    {
        HANDLE t;
        HWND wnd;
    };
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR 
    lpCmdLine, int nShowCmd)
    {
        HANDLE t = NULL;
        HWND wnd = NULL;
    
        // initialization of wnd and t by their functions
    
        MyHandles arg;
        arg.t = t;
        arg.wnd = wnd;
    
        _beginthreadex(NULL, 0, threadfunc, &arg, NULL, NULL, NULL);
    
        // doing some additional stuff
        // make sure arg doesn't go out of scope before the thread terminates...
    
        return 0;
    } 
    
    unsigned int __stdcall threadfunc(PVOID args)
    {
        MyHandles *parg = (MyHandles*) args;
    
        WaitForSingleObject(parg->t, INFINITE);
        EnableWindow(parg->wnd, TRUE);
    
        return 0;
    }
    

    Or, using dynamic allocation:

    struct MyHandles
    {
        HANDLE t;
        HWND wnd;
    };
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR 
    lpCmdLine, int nShowCmd)
    {
        HANDLE t = NULL;
        HWND wnd = NULL;
    
        // initialization of wnd and t by their functions
    
        MyHandles *arg = new MyHandles;
        arg->t = t;
        arg->wnd = wnd;
    
        if (!_beginthreadex(NULL, 0, threadfunc, arg, NULL, NULL, NULL))
            delete arg;
    
        // doing some additional stuff
        return 0;
    } 
    
    unsigned int __stdcall threadfunc(PVOID args)
    {
        MyHandles *parg = (MyHandles*) args;
    
        WaitForSingleObject(parg->t, INFINITE);
        EnableWindow(parg->wnd, TRUE);
    
        delete parg;
        return 0;
    }