在我的main函数中,有一些对象在后台工作,直到调用析构函数,如下面的代码片段所示:
#include <iostream>
class MyBackground {
public:
MyBackground()
{
m_workerThread = std::thread(&MyBackground::work, this);
}
~MyBackground()
{
g_exit = true;
workerThread.join();
}
private:
void work()
{
while(!m_exit);
}
private:
std::atomic<bool> m_exit{false};
std::thread m_workerThread;
};
int main(int argc, char* argv[])
{
MyBackground object;
// here ther's some async background work
return EXIT_SUCCESS;
// ~MyBackground -> here threads are stopped
}
我需要一种阻止main的方法,直到出现一些外部信号。我的第一次尝试是这样的:
#include <csignal>
#include <iostream>
#include <thread>
using namespace std
atomic<bool> g_Exit{false};
void signalExit(int)
{
g_Exit = true;
}
int main(int argc, char* argv[])
{
signal(SIGINT, signalExit);
signal(SIGTERM, signalExit);
MyBackground object;
while (!g_Exit)
this_thread::sleep_for(chrono::seconds{1});
// here ther's some async background work
return EXIT_SUCCESS;
// ~MyBackground -> here threads are stopped
}
但我不确定这是否合适。我认为最好使用condition_variables
,如下面的代码段:
#include <csignal>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std
bool g_exitFlag = false;
condition_variable g_exitCondition;
mutex g_exitMutex;
using Lock = unique_lock<mutex>;
void signalExit(int)
{
Lock lock{g_exitMutex};
g_exitFlag = true;
g_exitCondition.notify_one();
}
int main(int argc, char* argv[])
{
signal(SIGINT, signalExit);
signal(SIGTERM, signalExit);
MyBackground object;
Lock lock{g_exitMutex};
g_exitCondition.wait(lock, [](){return g_exitFlag;});
// here ther's some async background work
return EXIT_SUCCESS;
// ~MyBackground -> here threads are stopped
}
哪种最佳实施方式是正确的。他们是对的吗?我不是多线程编程的“专家”。
答案 0 :(得分:4)
为什么不是一个稍微不同的设计,你的后台工作线程不会被MyBackground
类创建和销毁,但是线程是在main
函数中创建的?然后main
函数可以在它退出之前简单地调用线程上的join
,它将阻塞直到后台线程完成。
像
这样的东西class MyBackground {
public:
void work()
{
while(!m_exit)
{
// Do background work
}
}
private:
std::atomic<bool> m_exit{false};
};
int main()
{
MyBackground background;
std::thread background_thread(&MyBackground::work, background);
// Do foreground work
background.join(); // Wait for background to exit
// Implicit return
}
另一个解决方案,如果线程在main
函数返回时应该继续,则是detach线程。然后它将独立于主线程工作,并且该过程实际上不会退出,直到线程退出。
请注意,这需要main
函数不仅返回或exit
,因为这将结束包括终止所有线程的进程。相反,你需要退出“主”线程。不幸的是,使用标准C ++线程接口是不可能的,但您必须使用平台本机函数。例如,在POSIX系统(如macOS和Linux)上,您使用pthread_exit
。
答案 1 :(得分:0)
你可以简单地在main()中使用std :: weak_ptr来检查强引用计数是否为nil来终止。将唯一的强引用指针传递给其他线程,以使main()能够平滑退出。使用std :: conditon_variable来避免关闭等待condition_variable的线程,以减少轮询期间的CPU使用率,以检查weak_ptr是否过期。
void worker_thread(std::shared_ptr<int>& pulse)
{
// do something
std::this_thread::sleep_for(std::chrono::seconds(2));
pulse.reset(); // reset to terminate main() too from any other threads
}
void main()
{
std::shared_ptr<int> pulse = std::make_shared<int>(1);
std::weak_ptr<int> weak_pulse(pulse);
std::thread([&](){ worker_thread(pulse); }).detach();
while (auto strong = weak_pulse.lock())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}