简体   繁体   中英

Is QThread::quit usabled from within the running thread

So I have the following situation:

I have a QThread that runs an eventloop (ie no custom run function). To stop the thread, I send a signal to a worker in that thread. This worker then does cleanups etc and at some point is done and quits the thread.

The problem I am facing right now is: If I invoke the workers stop method and then immediatly wait for the thread to finish it will never do so because the workers done signal does not get processed. Code:

class Worker {
signals:
    void done();

public slots:
    void stop() {
        //dummy code to illustrate what happens here:
        QTimer::singleShot(3000, this, &Worker::done);
    }
};

// in the main thread
auto thread = new QThread();
auto worker = new Worker();
worker->moveToThread(thread);
connect(worker, &Worker::done, thread, &QThread::quit); //implicitly a queued connection

// ...

QMetaObject::invokeMethod(worker, "stop", Qt::QueuedConnection);
thread->wait(); //blocks here forever, because the connect is queued

Now reason the problem is obvious - Because I block on the main thread the slot can never be invoked (because queued connection) and thus quit is never called. However, if I simply call QThread::quit (or QThread::exit ) directly from the worker (or use a DirectConnection ) then there is no problem anymore because the eventloop of the main thread is no longer required to process the event.

So the actual question here is: Is that allowed? Can I call QThread::quit from within the actual thread? Or can this create Race conditions, deadlocks and other problems like that. The documentation does not mark the method as threadsafe - but the thread that is managed by QThread might be an exception.

If you look in the file src/corelib/thread/qthread.cpp in the Qt source folder, you can see how quit() is implemented:

void QThread::quit()
{ exit(); }

.... and QThread::exit() is definitely intended to be called from within the thread itself. So the answer is yes, it's fine to call quit() from within the QThread's thread (although it might be a bit more usual to just call QThread::exit() directly instead).

Can I call QThread::quit from within the actual thread?

The question is actually backwards!

Since this method controls the event loop, and the event loop most definitely runs on the thread, the default assumption is that it's not a thread-safe method and thus can only be called from within the thread , since it controls a QEventLoop instance instantiated via QThread::run . That event loop, and its event dispatcher, are QObject s and most definitely have their thread() equal to the QThread instance in question.

But that wouldn't make QThread very useful, and thus QAbstractEventDispatcher::exit , and thus QEventLoop::quit and QThread::quit , are indeed thread-safe methods - you can call them from wherever, including from threads other than the one where the event loop lives. Both the event loop and thread's methods take extra precautions to protect their state from races, so the "and thus" part a few sentences ago is hand-wavey a bit.

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