In Qt, does a QThread's event loop block while a slot on a QObject owned by the event loop's thread is executing?

StackOverflow https://stackoverflow.com/questions/16989755

Question

I would like to confirm what I believe is a straightforward aspect of worker threads in Qt.

Suppose I create a QThread whose purpose is to manage time-consuming work in its corresponding thread. Furthermore, suppose I allow this thread's corresponding event loop to run by calling start() on the QThread. The work itself is performed by a member function (slot) that is signaled by the QThread's started() signal.

That is (copying from https://stackoverflow.com/a/11039216/368896):

class Task : public QObject
{
Q_OBJECT
public:
    Task();
    ~Task();
public slots:
    void doWork()
    {
        //very time-consuming code is executed here before the next line is reached...
        emit workFinished(); // Calls workFinished() signal (after a long time)
    }
signals:
    void workFinished();
};

// ... in the main thread:
QThread *thread = new QThread( );
Task    *task   = new Task();
task->moveToThread(thread);
connect( thread, SIGNAL(started()), task, SLOT(doWork()) );
connect( task, SIGNAL(workFinished()), thread, SLOT(quit()) );
//automatically delete thread and task object when work is done:
connect( thread, SIGNAL(finished()), task, SLOT(deleteLater()) );
connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) );
thread->start();

My question is the following. I understand that the worker thread's event loop will receive a trigger from the finished() signal in order to call the deleteLater() slot on the task instance. Also, this event loop will be running quite shortly after the doWork() function returns, and therefore it will be ready and available to process the trigger from the finished() signal that was just added to the worker thread's event queue by the call to finished() at the end of the doWork() function.

I would like to confirm that during the entire course of the time-consuming operation being executed inside doWork() (before finished() is emitted and before the doWork() function exits), that the event loop inside the worker thread is blocked on the slot function doWork() and therefore the worker thread will NOT be responsive to any slots triggered on any objects owned by the event loop's thread during the entire course of execution of the time-consuming doWork() function. (And that therefore, any such slots will only be executed after doWork() exits, once the worker thread's event loop is active again, and before the trigger from the finished() signal is handled.)

I suspect that this is the case, but I want to confirm.

Thanks!

Was it helpful?

Solution

The event loop of the worker thread will be blocked, i.e. you won't be able to process any events (including those which are used for 'queued' connections between signals and slots, which is what you get when doing signal-slot connections across threads) unless you explicitely trigger a call to the event loop object yourself.

You can however still have slots executed in your worker thread triggered by signals which are emitted from the worker thread, because those are plain function calls and don't need a running event loop.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top