创建线程不接受成员函数

时间:2010-05-23 13:40:16

标签: c++ windows callback function-pointers

我正在尝试为网络编程创建一个类。这将创建一个带有线程的通用套接字。

但是当我尝试使用createthread()创建线程时。第三个参数是产生错误。从网上我开始知道我不能使用成员函数作为createthread()的参数。

有什么方法可以实现这个目标吗?

3 个答案:

答案 0 :(得分:16)

处理此问题的最简单方法是创建一个“存根”函数,该函数将回调到您的类中。

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()允许您将参数传递给线程函数(CreateThread()调用的参数4)。您可以使用它来传递指向您的类的指针。然后,您可以将线程存根转换为指针返回正确的类型,然后调用成员函数。你甚至可以让“myThreadStub”成为“MyClass”的 static 成员,允许它 访问私人会员和数据。

如果安装了boost,则可以使用boost :: bind来执行此操作而不创建存根函数。我从来没有在Windows上尝试过,所以我不能肯定它会起作用(因为回调函数必须是一个WINAPI调用)但如果它确实有效,它看起来像:

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

其中thread函数是一个非静态成员函数,它接受一个void *参数。

答案 1 :(得分:3)

有一种简单的方法可以解决问题。

看看ThreadProc callback function


    DWORD WINAPI ThreadProc(
      __in  LPVOID lpParameter
    );

现在在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
    );

使用静态方法作为线程过程,但是从成员方法调用它,并将对象指针传递给它:


    #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;
      }
    };

抱歉,我没有足够的时间写一个好例子。但我认为你理解这种方式。

答案 2 :(得分:-1)