为什么我不能通过传入的 class 对象参数杀死 pthread

Why can't I kill pthread via class object argument passed in

我为 运行 我的 class 函数启动了一个后台线程,该任务作为无限循环执行,直到客户端决定停止。所以当创建 pthread 时 class 对象 'this' 被传递到线程中,我试图将它转换为 class 对象但是得到一个空对象,谁能向我解释为什么这是行不通的?

   void Camera::init()
   {
      typedef void *(*ThreadFuncPtr)(void *);
      this->quit=false;
      pthread_create(&acq, NULL, (ThreadFuncPtr)(&Camera::_acquireImages), this);
   }

   void Camera::stopAcquire()
   {
       this->quit=true;
   }

   void Camera::_acquireImages(void* ptr)
   {
       auto obj = (Camera*) ptr;  //obj after cast shows as NULL object
       while(!obj->quit){
       //do something
       }
       pthread_exit(NULL);
   }

So since when create pthread the class object 'this' is passed into thread

pthread_create 是一个 C 函数,期望函数签名是 void* (*)(void*) 但它现在有签名 void (Camera::*)(void*) 所以有两个错误:函数应该return void* 也是 non-static class 会员。要修复它,使函数 return void* 并使其成为 static:

void Camera::init()
{
    this->quit = false;
    // now that the function has the correct signature, you don't need
    // to cast it (into something that it wasn't)
    pthread_create(&acq, NULL, &Camera::acquireImages, this);
}

void Camera::stopAcquire()
{
    this->quit = true;
}

/*static*/ void* Camera::acquiredImages(void* ptr) // make it static in the declaration
{
    Camera& obj = *static_cast<Camera*>(ptr);

    while(obj.quit == false){
        //do something
    }
    return nullptr;
}

如果您使用的是 C++11(或更新版本),您应该查看标准 <thread>,这会让生活变得更轻松。

#include <thread>

struct Camera {
    void init() {
        quit = false;
        th = std::thread(&Camera::acquireImages, this);
    }
    ~Camera() {
        stopAcquire();
    }
    void acquireImages() {
        // no need for casting. "this" points at the object which started the thread
        while(quit == false) {
            std::cout << ".";
        }
    }
    void stopAcquire() {
        if(th.joinable()) {
            quit = true;
            th.join(); // hang here until the thread is done
        }
    }

    std::thread th{};
    bool quit = false;
};