在c++中,我可以创建一个线程并将其保存为类成员变量,以便它可以在析构函数中自动加入吗?



我有一个c++程序,我希望能够调用一个成员函数,它将启动一个单独的线程。当我分离线程时,它工作得很好,但是我没有办法加入它,所以我想将线程存储为成员变量,并在析构函数中自动加入它。

我认为这就是下面的代码要做的事情,然而,我得到了如下所示的输出,这使我相信线程从未连接。我如何加入一个线程保存为成员变量与成员函数?

请建议!

// thread example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <windows.h>
using namespace std;
void foo(int i) 
{
while(true){
cout << "Foo checkin" << endl;
Sleep(3000);
}
}
class ThreadHolder{
public:
ThreadHolder(int in){i = in;};
int i;
void start_threads(){
t = thread(foo, i);     // spawn new thread that calls foo()
std::cout << "foo startedn";
return;
}
~ThreadHolder();
private:
thread t;
};
ThreadHolder::~ThreadHolder(){
if (t.joinable()){
cout << "in destn";
t.join();
cout << "joinedn";
}
}

int main() 
{
cout << "in main" << endl;
ThreadHolder th(1);
th.start_threads();
cout << "back in main" << endl;
return 0;
}

输出:

in main
foo started
back in main
in dest
Foo checkin
Foo checkin
Foo checkin
Foo checkin
Foo checkin
Foo checkin

使用std::jthread获得更多:

class ThreadHolder{
public:
ThreadHolder(int in): i{in} {};
int i;
//The stop request function:
void stop_thread() {t.request_stop();};
void start_thread(){
t = jthread{[&,this](std::stop_token token){
while(!token.stop_requested()){
//...repeated logic
bar(this->i);
};
}};
std::cout << "foo startedn";
return;
};
//Rule of 0: no copy/move/dtor:
//~ThreadHolder();
private:
std::jthread t;
};

std::jthread的析构函数自动地为join提供了一个标准的机制来通知工作线程停止:

#include <iostream>
#include <chrono>
int main() 
{
using namespace std::chrono_literals;
std::cout << "in main" std::endl;
ThreadHolder th(1);
th.start_thread();
std::cout << "back in main" << std::endl;
std::this_thread::sleep_for(500ms);
std::cout << "notify the worker to stop" << std::endl;
th.stop_thread();
std::cout << "waiting for worker to stop" << std::endl;    
return 0;
}

请记住,工作函数(我的第一个代码片段中的lambda)必须经常检查std::stop_token是否有停止请求,否则程序可能会无限期地继续(直到工作线程完成)。如果你不打算等待完成,你可以detach线程;但是这会在从main返回时终止worker,并且可能泄漏worker函数所获得的资源。

最新更新