c++ - 如何在调用C++析构函数时优雅地通过阻塞调用来停止/销毁线程?

标签 c++ multithreading destructor stdthread blockingqueue

在下面的类中,工作线程在构造函数中启动。
工作人员对队列有阻塞 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/

相关文章:

c++ - Qt UI线程问题

Java线程池功能

c++ - 当你有一个二维数组(在 C++ 中)时,调用析构函数的正确方法是什么?

c++ - MFC C++ 应用程序的最佳 XML 序列化库

c++ - 用一个宏创建两个不同的代码块

c++11 使用 std::thread 时意外的多态性行为

c++ - 如何/何时使用虚拟析构函数?

c++ - Visual Studio std::stringstream pubsetbuf 不起作用

c# - ProgressChanged 回调上的 BackgroundWorker 和 UserState 问题

c++ - 不是默认析构函数导致不完整的类型错误