在工作线程中创建的QObject的线程亲和性会发生什么,然后终止? [英] What happens to the thread affinity of a QObject created within a worker thread which then terminates?
问题描述
假设我调用 QtConcurrent :: run()
,它在工作线程中运行一个函数,在该函数中我动态分配几个QObject(供以后使用)。因为它们是在工作线程中创建的,所以它们的线程亲和力应该是工作线程的亲和力。但是,一旦工作线程终止,QObject线程的亲缘关系应该不再有效。
问题:Qt自动将QObjects移动到父线程,
<$ c $
c> QThread 没有记录,当它完成后自动移动任何 QObject
,所以我想我们可以得出结论,它没有这样的事情。这种行为是非常令人惊讶的,并且与API的其余部分不一致。 为了完整性,我使用Qt 5.6测试:
QObject o;
{
QThread t;
o.moveToThread(& t);
for(int i = 0; i <2; ++ i)
{
t.start();
QVERIFY(t.isRunning());
QVERIFY(o.thread()==& t);
t.quit();
t.wait();
QVERIFY(t.isFinished());
QVERIFY(o.thread()==& t);
}
}
QVERIFY(o.thread()== nullptr);
回想一下 QThread
当 QThread
完成后,它会继续存在,并且生活在其中的对象继续居住在其中,但是它们不再处理事件。 QThread
可以重新启动(不推荐),此时将恢复事件处理(因此,相同的 QThread
当一个 QThread
被销毁时,其中存在的对象停止任何线程亲和。 文档不保证这一点,事实上
$ 假设我调用
QtConcurrent :: run()
,它会运行一个命令:b $ b 函数,并且在该函数中我动态地分配几个QObject(供以后使用)。因为它们是在工作线程中创建的,所以它们的线程亲和力应该是工作线程的亲和力。但是,一旦工作线程终止,QObject线程的亲缘关系应该不再有效。
QThread
在此场景中不终止。当由 QtConcurrent :: run
生成的任务完成时,正在运行的 QThread
将返回到 QThreadPool
,并且可以通过随后调用 QtConcurrent :: run
和 QObject $ c
QThread
继续居住。
QThreadPool :: globalInstance() - > setMaxThreadCount(1);
QObject * o = nullptr;
QThread * t = nullptr;
QFuture< void> f = QtConcurrent :: run([&] {
o = new QObject;
t = o-> thread();
QVERIFY(t == QThread :: currentThread());
});
f.waitForFinished();
QVERIFY(t == o-> thread());
QVERIFY(t-> isRunning());
f = QtConcurrent :: run([=] {
QVERIFY(t == QThread :: currentThread());
});
f.waitForFinished();
您可能需要手动将对象从 QThread
,然后它返回到 QThreadPool
,或者只是不使用 QtConcurrent :: run
。有一个 QtConcurrent :: run
任务构造 QObject
s超出任务是一个有问题的设计,包含。如@Mike所述, QtConcurrent :: run
使用的 QThread
没有事件循环。
Let's say I call QtConcurrent::run()
which runs a function in a worker thread, and in that function I dynamically allocate several QObjects (for later use). Since they were created in the worker thread, their thread affinity should be that of the worker thread. However, once the worker thread terminates, the QObject thread affinity should no longer be valid.
The question: Does Qt automatically move the QObjects into the parent thread, or are we responsible in moving them to a valid thread before the worker thread terminates?
QThread
is not documented to automatically move any QObject
s when it finishes, so I think we can already conclude that it does no such thing. Such behavior would be very surprising, and at odds with the rest of the API.
Just for completeness, I tested with Qt 5.6:
QObject o;
{
QThread t;
o.moveToThread(&t);
for (int i = 0; i < 2; ++i)
{
t.start();
QVERIFY(t.isRunning());
QVERIFY(o.thread() == &t);
t.quit();
t.wait();
QVERIFY(t.isFinished());
QVERIFY(o.thread() == &t);
}
}
QVERIFY(o.thread() == nullptr);
Recall that a QThread
is not a thread, it manages a thread.
When a QThread
finishes, it continues to exist, and the objects that live in it continue to live in it, but they no longer process events. The QThread
can be restarted (not recommended), at which point event processing will resume (so the same QThread
could then be managing a different thread).
When a QThread
is destroyed, the objects that lived in it cease to have any thread affinity. The documentation doesn't guarantee this, and in fact says "You must ensure that all objects created in a thread are deleted before you delete the QThread
."
Let's say I call
QtConcurrent::run()
which runs a function in a worker thread, and in that function I dynamically allocate several QObjects (for later use). Since they were created in the worker thread, their thread affinity should be that of the worker thread. However, once the worker thread terminates, the QObject thread affinity should no longer be valid.
The QThread
does not terminate in this scenario. When a task spawned by QtConcurrent::run
finishes, the QThread
it was running in is returned to the QThreadPool
and may be reused by a subsequent call to QtConcurrent::run
, and QObject
s living in that QThread
continue to live there.
QThreadPool::globalInstance()->setMaxThreadCount(1);
QObject *o = nullptr;
QThread *t = nullptr;
QFuture<void> f = QtConcurrent::run([&] {
o = new QObject;
t = o->thread();
QVERIFY(t == QThread::currentThread());
});
f.waitForFinished();
QVERIFY(t == o->thread());
QVERIFY(t->isRunning());
f = QtConcurrent::run([=] {
QVERIFY(t == QThread::currentThread());
});
f.waitForFinished();
You might want to manually move an object out of a QThread
before it is returned to the QThreadPool
, or just don't use QtConcurrent::run
. Having a QtConcurrent::run
task construct QObject
s which outlive the task is a questionable design, tasks should be self-contained. As noted by @Mike, the QThread
s used by QtConcurrent::run
do not have event loops.
这篇关于在工作线程中创建的QObject的线程亲和性会发生什么,然后终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!