关闭 QT GUI 后如何停止线程

Posted

技术标签:

【中文标题】关闭 QT GUI 后如何停止线程【英文标题】:How to stop a thread after we close the QT GUI 【发布时间】:2019-11-26 05:44:35 【问题描述】:

我正在 qt 中构建一个应用程序,我还使用 boost 在单独的线程中创建一个套接字服务器。

现在,当我关闭 QT 应用程序的 GUI 时,我希望线程也关闭。

但目前我无法理解当我们关闭 GUI 时如何发出关闭线程的信号。

int main(int argc, char *argv[])


    QApplication a(argc, argv);
    cont.SetName("RootItem");
    TreeModel* model = new TreeModel("RootElement", &cont);
    WavefrontRenderer w(model);
    w.show();    // Show the QT ui

    boost::asio::io_service io_service;
    server server1(io_service, 1980);
    boost::thread t(boost::bind(&io_service::run, &io_service));    

    return a.exec();


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#include "ConHandler.h"
#include "WavefrontRenderer.h"
class Server

private:
    tcp::acceptor acceptor_;
    void start_accept()
    
        // socket
        con_handler::pointer connection = con_handler::create(acceptor_.get_io_service());
        // asynchronous accept operation and wait for a new connection.
        acceptor_.async_accept(connection->socket(),
            boost::bind(&Server::handle_accept, this, connection,
                boost::asio::placeholders::error));
    
public:

    //constructor for accepting connection from client
    Server(boost::asio::io_service& io_service  ) : acceptor_(io_service, tcp::endpoint(tcp::v4(), 1980))
    
        start_accept();
    
    void handle_accept(con_handler::pointer connection, const boost::system::error_code& err)
    
        if (!err) 
            connection->start();
        
        start_accept();
    

;

/////////////////////////////////////// ///////////////////////////////////////// /////////////////////////////////////////

【问题讨论】:

【参考方案1】:

停止线程是指在io_service 实例上调用stop 方法。如果没有这个,boost::thread 的析构函数将在未完成的线程上被调用,这会导致 UB。

所有 GUI 事件都在exec 方法中处理。如果关闭所有窗口,则此方法结束。 main 也结束了,在主作用域结束时,所有局部变量都被销毁。

所以你可以为 lambda 做一个包装器,它会在 main 结束时被调用,然后你可以调用 stop 方法。然后线程的 dtor 将毫无问题地工作。

template<class F>
struct Cleaner 
    Cleaner(F in) : f(in) 
    ~Cleaner()  f(); 

    F f;
;

template<class F>
Cleaner<F> makeCleaner(F f) 
    return Cleaner<F>(f);


int main()

    boost::asio::io_service io_service;
    server server1(io_service, 1980);
    boost::thread t(boost::bind(&io_service::run, &io_service));   
    auto raii = makeCleaner( [&]() io_service.stop();  );
    return a.exec();

【讨论】:

以上是关于关闭 QT GUI 后如何停止线程的主要内容,如果未能解决你的问题,请参考以下文章

线程池的停止

停止 QRunnable 导致主窗口无法关闭

调用 exit() quit() 或 terminate() 后 Qt 线程执行不会停止

QT事件循环与QThread类的关闭quit(),wait()

即使使用 QThread,QT 程序也会停止

如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]