在下面的类中,工作线程在构造函数中启动。
工作人员对队列有阻塞 call 。
它可以按预期工作,但是当AsyncQueue
对象超出范围(出于某种原因)时,将调用其析构函数。同样,调用simple_queue对象的析构函数(我通过调试检查了什么)。
但是 worker 会怎样?因为它仍在等待队列的阻塞调用!
我观察到,没有在析构函数执行内调用impl_thread_.detach();
崩溃。
但是,我根本不知道这是否是解决方案。另外我不明白的是:尽管队列对象被破坏了,但阻塞调用并没有引发异常-实际上,我在catch处理程序中设置了一个断点。那么,这里发生了什么?实现该方案的正确方法是什么?我深深地感到,我在这里所做的并不像应有的那样;-)
template<typename T>
class AsyncQueue
{
public:
AsyncQueue() : impl_thread_(&AsyncQueue::worker, this)
{
tq_ = std::shared_ptr<simple_queue<T>>(new simple_queue<T>);
impl_thread_.detach();
}
//~AsyncQueue() = default;
~AsyncQueue() {
std::cout << "[" << boost::this_thread::get_id() << "] destructor AsyncQueue" << std::endl;
return;
}
private:
std::thread impl_thread_;
std::shared_ptr<simple_queue<T>> tq_;
void worker()
{
try {
while (true)
{
boost::optional<T> item = tq_->deq(); // blocks
...
...
...
}
}
catch (exception const& e) {
return;
}
}
public:
...
...
};
最佳答案
如果可以的话,最简单的方法是在析构函数中在eq队列中发送停止 token ,并在worker中检查该停止 token 以将其退出。首先卸下分离器。
~AsyncQueue() {
_eq.add(stopToken); // what ever your can use here. else use an atomic bool
std::cout << "[" << boost::this_thread::get_id() << "] destructor AsyncQueue" << std::endl;
impl_thread_.join();
}
(未经测试,不完整)
关于c++ - 如何在调用C++析构函数时优雅地通过阻塞调用来停止/销毁线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60110048/