5

I can't pass a pointer to method to the CreateThread function, of course. What should I do?

KOLANICH
  • 2,904
  • 2
  • 20
  • 20

6 Answers6

7

If using a class, some pattern like this usually works well:

.h

static UINT __cdecl StaticThreadFunc(LPVOID pParam);
UINT ThreadFunc();

.cpp

// Somewhere you launch the thread
AfxBeginThread(
    StaticThreadFunc,
    this);  

UINT __cdecl CYourClass::StaticThreadFunc(LPVOID pParam)
{
    CYourClass *pYourClass = reinterpret_cast<CYourClass*>(pParam);
    UINT retCode = pYourClass->ThreadFunc();

    return retCode;
}

UINT CYourClass::ThreadFunc()
{ 
    // Do your thing, this thread now has access to all the classes member variables
}
DanDan
  • 10,462
  • 8
  • 53
  • 69
5

I often do this:

class X {
private:
    static unsigned __stdcall ThreadEntry(void* pUserData) {
        return ((X*)pUserData)->ThreadMain();
    }

    unsigned ThreadMain() {
         ...
    }
};

And then I pass this as user data to the thread creator function (_beginthread[ex], CreateThread, etc)

Jörgen Sigvardsson
  • 4,839
  • 3
  • 28
  • 51
4

The most common way is to create a Thread class that has a run() method and a start() method (these names borrowed from the Java Thread class). run() is a pure virtual that you overload in a class derived from Thread to do the actual work. The method start() internally calls CreateThread passing the this pointer via reinterpret_cast to void*. The Thread class has also a threadEntryPoint() static function that you pass to CreateThread. In threadEntryPoint() you do a reinterpret_cast back to Thread* and then call run() on it.

If there's one situation in which you just want a method of another class to be executed on a separated thread (without having to inherit from the Thread class) you can create a Thread-derived class that receives a pair object+method pointers in the constructor, and calls them in run(). To ease things up, make this derived class a template. Also take a look on boost for functor adaptors.

Fabio Ceconello
  • 15,819
  • 5
  • 38
  • 51
  • thanks. as i understood, i only nedd to add one static function to my class and one method to start, threadEntryPoint functionality will be realized in the statiс method. – KOLANICH Jun 09 '11 at 16:03
  • Yes, if you want to do this once-only it's as simple as that. If you want to reuse it in other places, it'd be better to isolate the code in a separated class. – Fabio Ceconello Jun 09 '11 at 16:08
1

CreateThread won't take a pointer to a member function. You can wrap the member function in a static function which takes the object pointer through lpParameter.

pepsi
  • 6,785
  • 6
  • 42
  • 74
1

CreateThread's lpStartAddress is of type DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter) and this is incompatible with the member function since the member function has an implicit this pointer in its signature. So create a static function and pass the class pointer as the argument to the thread function.

Vishal
  • 1,199
  • 1
  • 8
  • 13
-1

If you are talking about Native CreateThread Method you would probably need to do following

CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MyThreadProc,NULL,NULL,&threadId);

Where your callback method is defined as

void MyThreadProc()
{
}
crypted
  • 10,118
  • 3
  • 39
  • 52
  • 3
    You don't want to do this - the cast here is a problem: generally speaking, you should never cast a function just to make things work. Instead you should pass MyThreadProc without a cast, and then change void MyThreadProc() to be DWORD WINAPI MyThreadProc(LPVOID), which is what CreateThread is expecting. Passing a function with a different number or type of params or calling convention than an API is expecting can lead to a messed-up stack. – BrendanMcK Jun 09 '11 at 22:05