我有一个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函数所获得的资源。