gpt4 book ai didi

c++ - QThread::create 在 UI 线程上运行

转载 作者:行者123 更新时间:2023-11-30 03:13:39 25 4
gpt4 key购买 nike

我的应用程序需要多线程。根据 Qt 的文档,有多种方法可以实现这一点。

简要概述QThread方法:

  1. 子类化 QThread 并重新实现 run() ( doc )。

  2. 创建一个继承自 QObject 的对象与 Q_OBJECT带有 doWork 的宏(用于信号/插槽)方法,创建一个 QThread对象,使用 QObject::moveToThread(QThread*)并调用QThread::start() ( docs , wiki )

  3. 使用 QThread::create(Function &&f)QThread::create(std::function<>)用于 lambda 语法。

我选择使用第三个选项进行测试。我还实现了一个名为 QThreading 的多线程库基于选项 2,使用 QWorkerThread它充当一个带有 QThread 的 Controller 对象和 QObject作为对象。 这个库也给出了如下所示的相同结果。


既然文档已经不在了,问题来了。

使用 QThread::create(Function &&f) ,我正在测试 QThread 是否独立于 UI 线程运行。下面是一个 MCVE 示例:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qsrand(0);
QThread *thread = nullptr;
auto threadTest = std::function<void ()> ([&]() {

if(thread->thread() == a.thread()) {
qDebug() << "UI Thread in use";
} else {
qDebug() << "Worker thread in use";
}

for (int var = 0; var < INT_MAX; ++var) {
int r = qrand() % 100;
thread->thread()->msleep(r);
qDebug() << "[Worker Thread " << thread->thread()->currentThreadId() << "] " << r;
}
});
thread = QThread::create(threadTest);
thread->start();

for (int var = 0; var < INT_MAX; ++var) {
// sleep thread 0-100ms
int r = qrand() % 100;
a.thread()->msleep(r);
qDebug() << "[UI Thread " << a.thread()->currentThreadId() << "] " << r;
}

return a.exec();
}

输出是:

UI Thread in use
[Worker Thread 0x47e4 ] 41
[UI Thread 0x10c0 ] 38
[UI Thread 0x10c0 ] 19
[UI Thread 0x10c0 ] 38
[Worker Thread 0x47e4 ] 67
[UI Thread 0x10c0 ] 37
[Worker Thread 0x47e4 ] 34
[Worker Thread 0x47e4 ] 0
[UI Thread 0x10c0 ] 55
[Worker Thread 0x47e4 ] 69
[Worker Thread 0x47e4 ] 24
[UI Thread 0x10c0 ] 97
[Worker Thread 0x47e4 ] 78
[UI Thread 0x10c0 ] 65
[Worker Thread 0x47e4 ] 58
[UI Thread 0x10c0 ] 85
[Worker Thread 0x47e4 ] 62
[UI Thread 0x10c0 ] 50
[Worker Thread 0x47e4 ] 64
[UI Thread 0x10c0 ] 12
[Worker Thread 0x47e4 ] 5
[Worker Thread 0x47e4 ] 45

注意事项

  • UI 线程 ID:0x10c0

  • 工作线程 ID:0x47e4

问题出在哪里

UI Thread in use

让我感到困惑的是不同的线程地址,但工作线程仍然等于 UI 线程。

这让我有 2 个解释:

  1. QThread::currentThread总是返回主机/主线程(难以置信,使函数有些无意义)

  2. QThread *thread存在于 Main UI Thread 内部,因此(获取父线程)总是返回父线程,即 ParentThread == WorkerThread (ParentThread)

我想念如何理解 QThread有用吗?

最佳答案

  1. 如果您想知道它是否在主线程中运行,那么您应该将 currentThread 与 QCoreApplication 线程进行比较:
if(QCoreApplication::instance()->thread() == QThread::currentThread()) {
qDebug() << "UI Thread in use";
} else {
qDebug() << "Worker thread in use";
}
  1. QThread 不是一个线程,是一个线程处理程序,如the docs指出:

Detailed Description

A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.

此外,QThread 是一个 QObject,它存在于父线程中,或者如果它没有父线程则创建它的位置 the docs指出:

Thread Affinity

A QObject instance is said to have a thread affinity, or that it lives in a certain thread. When a QObject receives a queued signal or a posted event, the slot or event handler will run in the thread that the object lives in.

Note: If a QObject has no thread affinity (that is, if thread() returns zero), or if it lives in a thread that has no running event loop, then it cannot receive queued signals or posted events.

By default, a QObject lives in the thread in which it is created. An object's thread affinity can be queried using thread() and changed using moveToThread().

All QObjects must live in the same thread as their parent. Consequently:

  • setParent() will fail if the two QObjects involved live in different threads.
  • When a QObject is moved to another thread, all its children will be automatically moved too.
  • moveToThread() will fail if the QObject has a parent.
  • If QObjects are created within QThread::run(), they cannot become children of the QThread object because the QThread does not live in the thread that calls QThread::run().

Note: A QObject's member variables do not automatically become its children. The parent-child relationship must be set by either passing a pointer to the child's constructor, or by calling setParent(). Without this step, the object's member variables will remain in the old thread when moveToThread() is called.

在你的例子中,“thread”对象是一个 QObject,它存在于主线程中,因为它没有父线程,它是在那里创建的,它处理另一个线程。

更新:

MWE

#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qsrand(0);
auto threadTest = std::function<void ()> ([&]() {
if(QCoreApplication::instance()->thread() == QThread::currentThread()) {
qDebug() << "UI Thread in use";
} else {
qDebug() << "Worker thread in use";
}

for (int var = 0; var < INT_MAX; ++var) {
int r = qrand() % 100;
QThread::msleep(r);
qDebug() << "[Worker Thread " << QThread::currentThreadId() << "] " << r;
}
});
QThread *thread = QThread::create(threadTest);
thread->start();

int var = 0;
std::function<void ()> timerTest;
timerTest = [&](){
int r = qrand() % 100;
qDebug() << "[UI Thread " << QThread::currentThreadId() << "] " << r;
++var;
if (var < INT_MAX)
QTimer::singleShot(r, timerTest);
};
int r = qrand() % 100;
QTimer::singleShot(r, timerTest);

return a.exec();
}

输出:

<b>Worker thread in use</b>
[UI Thread 0x7fc6222993c0 ] 94
[Worker Thread 0x7fc621f62700 ] 71
[UI Thread 0x7fc6222993c0 ] 86
[Worker Thread 0x7fc621f62700 ] 94
[UI Thread 0x7fc6222993c0 ] 37
[Worker Thread 0x7fc621f62700 ] 86
...

关于c++ - QThread::create 在 UI 线程上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58511891/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com