[英]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). 我有一个运行事件循环的QThread(即没有自定义运行功能)。 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. 我现在面临的问题是:如果我调用worker的stop方法,然后立即等待线程完成,它将永远不会这样做,因为没有处理好worker的信号。 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. 现在原因很明显了-因为我在主线程上阻塞,所以永远无法调用该插槽(因为已排队连接),因此永远不会调用quit。 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. 但是,如果我直接从工作线程(或使用
DirectConnection
)直接调用QThread::quit
(或QThread::exit
),那么就不再存在问题,因为不再需要主线程的eventloop来处理事件。
So the actual question here is: Is that allowed? 因此,这里的实际问题是:允许这样做吗? Can I call
QThread::quit
from within the actual thread? 我可以在实际线程中调用
QThread::quit
吗? 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.
文档没有将该方法标记为线程安全的-但是,由QThread管理的线程可能是一个例外。
If you look in the file src/corelib/thread/qthread.cpp
in the Qt source folder, you can see how quit()
is implemented: 如果您查看Qt源文件夹中的
src/corelib/thread/qthread.cpp
文件,则可以看到quit()
的实现方式:
void QThread::quit()
{ exit(); }
.... and QThread::exit()
is definitely intended to be called from within the thread itself. ....和
QThread::exit()
绝对旨在从线程本身内部调用。 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). 因此答案是肯定的,可以从QThread的线程中调用
quit()
(尽管直接调用QThread::exit()
可能更常见)。
Can I call
QThread::quit
from within the actual thread?我可以在实际线程中调用
QThread::quit
吗?
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
. 由于此方法控制事件循环,并且事件循环最明确地在线程上运行,因此默认假设是它不是线程安全的方法,因此只能从线程内调用 ,因为它控制通过实例化的
QEventLoop
实例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. 该事件循环及其事件分发程序是
QObject
并且绝对可以使它们的thread()
等于所讨论的QThread
实例。
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. 但这并不能使
QThread
变得非常有用,因此QAbstractEventDispatcher::exit
以及QEventLoop::quit
和QThread::quit
确实是线程安全的方法-您可以从任何地方调用它们,包括从一个线程以外的线程调用事件循环所在的位置。 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. 事件循环和线程的方法都采取了额外的预防措施来保护其状态免受种族的影响,因此,几句话之前的“因而”部分有点让人费解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.