在工作线程中创建的QObject的线程亲和性会发生什么,然后终止? [英] What happens to the thread affinity of a QObject created within a worker thread which then terminates?

查看:236
本文介绍了在工作线程中创建的QObject的线程亲和性会发生什么,然后终止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我调用 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 生活在 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 QObjects 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 QObjects 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 QObjects which outlive the task is a questionable design, tasks should be self-contained. As noted by @Mike, the QThreads used by QtConcurrent::run do not have event loops.

这篇关于在工作线程中创建的QObject的线程亲和性会发生什么,然后终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆