简体   繁体   English

了解std :: thread语义,并以worker函数作为类成员

[英]understanding std::thread semantic with worker function as class member

To implement the logic when contructed object starts background thread for real work, I'm using a pattern like this (simplified): 为了在构造对象启动后台线程以进行实际工作时实现逻辑,我使用了这种模式(简化):

class A {
    std::thread t{&A::run, this};
    std::atomic_bool done;
    // variables are the question about
    std::vector<std::thread>  array_for_thread_management;

    // ... and other members
protected:
    void run() {
        ...
        array_for_thread_management.push_back([](){...});
        ...
   }
public:
    A() = default;
    // all other constructors deleted because of used 
    // some members like std::atomic_bool done;
    ~A() {
        done = true;
        bi::named_condition         cnd{bi::open_only, "cnd"};
        cnd.notify_one();

        if (t.joinable())
            t.join();

        for(std::thread& worker : array_for_thread_management) {
            if (worker.joinable()) worker.join();
        }
    }


};

If I'm adding a push of child threads in primary background thread into a vector in run() member, the object hangs on destructor. 如果我要将主后台线程中的子线程推入run()成员中的向量中,则该对象将挂在析构函数上。 even there is no real threads in a vector, just started this without connections from outside and try to stop this by destructor 即使向量中没有真正的线程,也可以在没有外部连接的情况下启动此线程,并尝试通过析构函数将其停止

Of course, once you have this pointer in your run method, you can access class members via this pointer. 当然,一旦在run方法中有了this指针,就可以通过该指针访问类成员。 I guess the problem with your code is that the thread is spawned before any other members are initialized, as it is the first member in your class definition. 我想您的代码的问题在于,线程是初始化任何其他成员之前生成的,因为它是类定义中的第一个成员。 I suspect with the following definition of class A you'll have no problems with accessing member variables: 我怀疑使用class A的以下定义,访问成员变量不会有问题:

class A {
    std::atomic_bool done;
    // variables are the question about
    int i;
    std::string s;
    std::vector<std::string> v;
    // and only after everything above is initialized:
    std::thread t{&A::run, this}; // spawn a thread
    // ...
}

However, personally I would prefer having a separate method start() which spawns a thread to spawning it inside class constructor implicitly. 但是,个人而言,我更喜欢有一个单独的方法start()来生成线程,而不是隐式在类构造函数中生成线程。 It may look like this: 它可能看起来像这样:

class A
{
    std::unique_ptr<std::thread> t;
    std::atomic<bool> some_flag;

public:
    void start()
    {
        t.reset(new std::thread(&A::run, this));
    }

private:
    void run()
    {
        some_flag.store(true);
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM