简体   繁体   中英

How to stop a thread after we close the QT GUI

I am building a application in qt where i am also creating a socket Server in a separate thread using boost.

Now when i close the GUI of the QT application i want the thread to be closed also.

But currently i am not able to understand how do we signal the thread to close when we close the 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();
    }

};

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

By saying stop thread you mean call stop method on io_service instance. Without this, destructor of boost::thread will be invoked on unfinished thread, what leads to UB.

All GUI events are processed in exec method. If you close all windows, this method ends. main ends as well, and at the end of main scope all local variables are destroyed.

So you can just make wrapper for lambda, which will be called at the end of main, and there you can call stop method. Then dtor of thread will work without any problems.

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM