Results 1 to 6 of 6

Thread: Waiting for a thread to finish without blocking the main event loop

  1. #1
    Join Date
    May 2007
    Posts
    131
    Thanks
    17
    Thanked 4 Times in 2 Posts

    Default Waiting for a thread to finish without blocking the main event loop

    The following code is called by a subclass of QThread in the cancel method. I need to wait for the thread to finish, but I can't use QThread::wait() because I must not block the main UI thread. Following the advice here, I tried to use a QEventLoop.
    Qt Code:
    1. QEventLoop eventLoop;
    2. connect(this, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    3. // Race condition
    4. if (!isFinished())
    5. eventLoop.exec();
    To copy to clipboard, switch view to plain text mode 
    The problem is that the thread might emit the finished() signal after the call to isFinished(), but before the call to exec(). Unfortunately, exec() will not exit in this case. How can I prevent the dead lock if I don't want to add a timeout?

  2. #2
    Join Date
    Sep 2011
    Posts
    1,241
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Waiting for a thread to finish without blocking the main event loop

    "The following code is called by a subclass of QThread in the cancel method."

    why would you be making an event loop in a cancel method?
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  3. #3
    Join Date
    May 2007
    Posts
    131
    Thanks
    17
    Thanked 4 Times in 2 Posts

    Default Re: Waiting for a thread to finish without blocking the main event loop

    Because I want to wait for the thread to finish. I set a flag in cancel() which is checked by the thread's main while-loop in the run() method.

  4. #4
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Waiting for a thread to finish without blocking the main event loop

    First of all, do you really have to wait for the thread to terminate in a local event loop? Can't you simply connect the QThread's finished() signal to some slot and let the main event loop deal with it? (Asynchronous-style programming vs your current synchronous style.)

    To answer your question, there is no race condition here. Indeed, the QThread object lives in the main thread and its finished() signal will only have a chance of being emitted when control returns to an event loop, i.e. during the QEventLoop's exec().
    Last edited by yeye_olive; 22nd June 2012 at 13:21.

  5. The following user says thank you to yeye_olive for this useful post:

    bmn (22nd June 2012)

  6. #5
    Join Date
    May 2007
    Posts
    131
    Thanks
    17
    Thanked 4 Times in 2 Posts

    Default Re: Waiting for a thread to finish without blocking the main event loop

    Yes, I really need to wait. This happens during shutdown, and I need to keep certain objects alive until the thread is finished.

    Thank you for your answer. You're right, there is no race condition.
    Qt Code:
    1. QEventLoop eventLoop;
    2. connect(this, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    3. // Note: One might think that there is a race condition where finished() is emitted after
    4. // the call to isFinished(), but before exec(). However, the finished() signal is emitted from
    5. // the QThread, so if the current call lives in another thread (e. g. the main UI thread), the
    6. // Qt::AutoConnection behaves like a Qt::QueuedConnection, and the slot is handled in the
    7. // receiver's thread, i. e. in eventLoop.exec().
    8. if (!isFinished())
    9. eventLoop.exec();
    To copy to clipboard, switch view to plain text mode 

  7. #6
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Waiting for a thread to finish without blocking the main event loop

    I may have written something wrong above: there is no guarantee that QThread::finished() will be emitted from the main thread; it may well be emitted from the thread controlled by the QThread instance (and, looking at Qt's source, it indeed seems to be the case, at least on some platforms). But then, as you stated in your comment, the auto connection to QEventLoop::exec() behaves as a queued one. In both cases the signal is handled in the main thread, during QEventLoop::exec(). No race condition.

    By the way, I usually call QThread::wait() even after having received finished(). I could not find anywhere a confirmation that all resources were guaranteed to be freed without it.

    As for my suggestion of using the main event loop instead of a local one, I remembered solving the exact same problem you have by reimplementing the closeEvent() method of the main window of the GUI to prevent if from closing, asking the thread to exit instead. Only upon receiving QThread::finished() would I close the window. In the meantime the GUI would still respond.

Similar Threads

  1. Replies: 5
    Last Post: 8th February 2012, 09:56
  2. Main loop thread loop communication
    By mcsahin in forum Qt Programming
    Replies: 7
    Last Post: 25th January 2011, 16:31
  3. Replies: 10
    Last Post: 15th January 2010, 14:35
  4. QThread event loop blocking the GUI
    By JoeMerchant in forum Qt Programming
    Replies: 4
    Last Post: 18th July 2009, 07:54
  5. Main Thread Event loop
    By ^NyAw^ in forum Qt Programming
    Replies: 1
    Last Post: 20th March 2007, 12:10

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.