[SOLVED] How to stop asynchronous operation when closing



  • Hello. Please take the following example functions on a QMainWindow:

    @
    void MyWindow::launchServer()
    {
    Server1 *server1 = new Server1;

    QThread *server1Thread = new QThread(this);

    server1->moveToThread(server1Thread);

    server1->connect(server1Thread, SIGNAL(started()), SLOT(start()));

    // Note that Server1::stop() emits its own finished() signal, used below
    // to stop the thread
    server1->connect(this, SIGNAL(finished()), SLOT(stop()));

    server1Thread->connect(server1, SIGNAL(finished()), SLOT(quit()));

    server1->connect(server1Thread, SIGNAL(finished()), SLOT(deleteLater()));
    server1Thread->connect(server1Thread, SIGNAL(finished()), SLOT(deleteLater()));
    }

    void MyWindow::closeEvent(QCloseEvent *event)
    {
    emit finished();

    QMainWindow::closeEvent(event);
    }
    @

    So MyWindow::launchServer() is called at some point, then I close the window.

    About 50% of the time, the above works fine. The other 50%, I get a "QThread: Destroyed while thread is still running" message. When that happens, I've learned by strategically placing printouts that, while the MyWindow::finished() signal is emitted and the Server1::finished() signal is emitted, the program seems to quit before any further handling can happen (i.e. the QThread::quit() slot). That's not ideal, and I hate seeing that message. Is there a better way to do this?

    Thank you!


  • Moderators

    When a parent QObject is deleted, so will its children. So, you have 2 pathways for server1Thread to get deleted:

    The signal/slot chain that starts with MyWindow::finished()

    The deletion of its parent window

    Both pathways are triggered upon closing your window (probably because the window's Qt::WA_QuitOnClose or Qt::WA_DeleteOnClose flags are set), but the order of execution is not guaranteed. If pathway #1 "wins the race", everything's fine; otherwise, you get your warning message.

    By calling either QWidget::setAttribute() or QApplication::setQuitOnLastWindowClosed(), you can prevent your application from quitting early, which prevents MyWindow from getting deleted early, which prevents your QThread from getting deleted early.

    Then, you can set up an alternate quitting pathway by connecting server1Thread->finished() or server1Thread->destroyed() to qApp->quit()



  • @JKSH, that makes perfect sense, thank you. I ended up simply ignoring the close until I received QThread::finished(). I didn't want to connect QThread::finished() directly up to qApp::quit() since the server (and thus thread) could actually be closed by other means as well.

    Thank you again!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.