【问题标题】:Access class variable from std::thread从 std::thread 访问类变量
【发布时间】:2014-09-25 16:36:06
【问题描述】:

我有以下类启动一个新的 std::thread。我现在希望线程访问该类的成员变量。到目前为止,我无法弄清楚如何做到这一点。 在我的 MyThread 函数中,我想检查 m_Continue。

我尝试在创建线程时传入“this”,但出现错误:

错误 1 ​​错误 C2197: 'void (__cdecl *)(void)' : 调用 c:\program files (x86)\microsoft visual studio 11.0\vc\include\functional 1152 1 MyProject 的参数太多。

class SingletonClass
{
public:
    SingletonClass();
    virtual ~SingletonClass(){};

    static SingletonClass& Instance();
   void DoSomething();
private:
    static void MyThread();

    std::thread* m_Thread;
    bool m_Continue;
};

SingletonClass::SingletonClass()
{
    m_Continue = true;
    m_Thread= new std::thread(MyThread, this);
}

void SingletonClass::MyThread()
{
    while(this->m_Continue )
    {
       // do something
    }
}

void SingletonClass::DoSomething()
{
    m_Continue = false;
}

SingletonClass& SingletonClass::Instance()
{
    static SingletonClass _instance;
    return _instance;
}


int _tmain(int argc, _TCHAR* argv[])
{
    SingletonClass& singleton = SingletonClass::Instance();
    singleton.DoSomething();    

    return 0;
}

我该怎么做?

【问题讨论】:

  • 无关:没有理由动态分配线程,m_thread 可能只是您分配的std::threadm_thread = std::thread{MyThread, this};。此外,由于SingletonClass::m_Continue 上的数据竞争,您的程序具有未定义的行为,因为它可能在生成的线程中被访问,同时在主线程中被修改。您需要将其设为std::atomic<bool> 或使用std::mutex 保护对其的访问。

标签: c++ multithreading c++11


【解决方案1】:

如果你想从线程函数中访问this,那么它不应该是静态的:

void MyThread();

现在您可以简单地将this 作为第二个thread 构造函数参数传递,就像您尝试的那样;但是,作为非静态成员,您需要限定其名称:

m_Thread= new std::thread(&SingletonClass::MyThread, this);

或者,您可能会发现 lambda 更易于阅读:

m_Thread= new std::thread([this]{MyThread();});

但是你不应该像这样乱用指针和new;将成员变量设为thread 对象并在初始化列表中对其进行初始化:

SingletonClass::SingletonClass() :
    m_Continue(true), m_Thread([this]{MyThread();})
{}

确保在它访问的任何其他成员之后声明m_Thread;并确保您停止并加入析构函数中的线程,或者更早。

最后,m_Continue 应该是std::atomic<bool>,以便在一个线程上设置它并在另一个线程上以明确的行为读取它。

【讨论】:

    【解决方案2】:

    替换

    static void MyThread();

    void MyThread();

    作为

    this 不能在static 方法中访问。

    【讨论】:

      【解决方案3】:

      如果成员变量是公共的,您可以访问它,或者您可以使用类似“bool shallContinue()”的方法返回 m_Continue。

      现在你如何做到这一点。检查以下修改后的sn-p:

      static void SingletonClass::MyThread(SingleTonClass *arg)
      {
          while(arg->shallContinue() )
          {
             // do something
          }
      }
      

      下面是一个完整的例子:

      #include <iostream>
      #include <thread>
      #include <unistd.h>
      using namespace std;
      
      class A
      {
      public:
          A(int x) : a(x) 
          {
              thr = new thread(myThread, this);
          }
          static void myThread(A *arg)
          {
              arg->show();
      
          }
          void show()
          {
              cout << a << endl;
          }
      private:
          int a;
          thread *thr;
      };
      
      int main()
      {
          A a(1);
          sleep(2); 
          return 0;
      }
      

      【讨论】:

      • 无论它是否公开,您都可以从成员函数中访问它。当您可以将其设为非静态时,为什么还要使用 void* 参数?
      • 这只是快速打字。有很多方法可以实现这一点,实际上是静态、非静态等。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      相关资源
      最近更新 更多