Create thread is not accepting the member function

10,060

Solution 1

At lost I got it, the very fact is, in CreateThread if you pass the socket then there is no trouble. Because CreateThread is taking care of that socket. But if you pass as an object which is having that socket, then CreateThread is not taking care of the socket, and it is ends up in invalid socket in the new thread.

The successed code below

SOCKET s=socket(....);
bind(s,...);
listen(s,...);
SOCKET temp=accept(s,(sockaddr *)&addrNew,&size);
DWORD threadId;
HANDLE thread=CreateThread(NULL,0,&MyThreadFunction,(LPVOID)(temp),0,&threadId);

Solution 2

The easiest way to handle this is to create a "stub" function which calls back into your class.

UINT tid
HANDLE hThread = CreateThread(NULL, 0, myThreadStub, this, 0, &tid);

....

unsigned long WINAPI myThreadStub(void *ptr) 
{
    if (!ptr) return -1;
    return ((MyClass*)ptr)->ThreadMain();
}

CreateThread() allows you to pass an argument to the thread function (parameter 4 of the CreateThread() call). You can use this to pass a pointer to your class. You can then have the thread stub cast that pointer back into the proper type and then call a member function. You can even have "myThreadStub" be a static member of "MyClass", allowing it to access private members and data.

If you have boost installed, you may be able to use boost::bind to do this without creating a stub function. I've never tried that on windows, so I can't say for sure it would work (because the callback function must be a WINAPI call) but if it does work it would look something like:

HANDLE hThread = CreateThread(NULL, 0, boost::bind(&MyClass::ThreadFunction, this), NULL, 0, &tid);

Where thread function is a non-static member function which takes a single void * argument.

Solution 3

There's an easy way to solve the problem.

Take a look at ThreadProc callback function:


    DWORD WINAPI ThreadProc(
      __in  LPVOID lpParameter
    );

And now at CreateThread function:


    HANDLE WINAPI CreateThread(
      __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in       SIZE_T dwStackSize,
      __in       LPTHREAD_START_ROUTINE lpStartAddress,
      __in_opt   LPVOID lpParameter,
      __in       DWORD dwCreationFlags,
      __out_opt  LPDWORD lpThreadId
    );

Use a static method as thread procedure, but call it from a member method, and pass the object pointer to it:


    #include <windows.h>

    class MyClass {
     public:
      void CreateThreadForObject() {
        LPSECURITY_ATTRIBUTES security_attributes = 0;
        SIZE_T stack_size = 0;
        LPTHREAD_START_ROUTINE start_routine = &MyClass::ThreadProcForObject;
        LPVOID param = this;
        DWORD creation_flags = 0;
        LPDWORD thread_id = 0;
        CreateThread(security_attributes, stack_size, start_routine, param,
                     creation_flags, thread_id);
      }

     private:
      static DWORD WINAPI ThreadProcForObject(LPVOID param) {
        MyClass* instance = reinterpret_cast<MyClass*>(param);
        if (!instance) return 1;
        // ...
        return 0;
      }
    };

Sorry, I just don't have enough time to write a good example. But I think you understand the way.

Share:
10,060
prabhakaran
Author by

prabhakaran

A newbie to qt,openGL,NetworkProgramming Know python,perl,shell scripting. A well versed(medium level) C++,linux,perl,c# programmer Crawling around javascript,xul and new technologies. I am a Linux lover got tricked into windows.

Updated on June 15, 2022

Comments

  • prabhakaran
    prabhakaran almost 2 years

    I am trying to create a class for network programming. This will create a general purpose socket with thread.

    But when I tried to crete the thread using createthread(). The third argument is producing errors. And from the net I came to know that I can't use the member functions as an argument to the createthread().

    Is there any thing by which I can achieve this?