当构造对象为实际工作启动后台线程时实现逻辑,我正在使用这样的模式(简化):
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();
}
}
};
如果我将主要后台线程中的子线程推送添加到run()成员中的向量中,则该对象将在析构函数上挂起。 即使在向量中没有真正的线程,只是在没有外部连接的情况下启动它并尝试通过析构函数来阻止它
答案 0 :(得分:2)
当然,一旦在this
方法中有run
指针,就可以通过此指针访问类成员。我猜你的代码的问题是在任何其他成员被初始化之前产生线程,因为它是你的类定义中的第一个成员。我怀疑使用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
// ...
}
但是,我个人更喜欢使用一个单独的方法start()
,它产生一个线程来隐式地在类构造函数中生成它。它可能看起来像这样:
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);
}
};