- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我在使用 QThreads
时遇到了一些问题这让我在找到合适的组合之前探索了不同的组合。然而,当涉及到事件循环和信号槽处理时,我仍然不完全理解在下面显示的四种情况下真正发生了什么。
我在 OUTPUT 部分添加了一些注释,但正如您所看到的,我不确定我对导致观察到的行为的原因的假设是否正确。另外我不确定 case 3
是可能在实际代码中使用的东西。这是我的测试代码(只有 main.cpp
因每种情况而异):
worker.h:
#include <QObject>
#include <QDebug>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0) { this->isRunning_ = false;}
bool isRunning() const { return isRunning_; }
signals:
void processingFinished();
void inProgress();
public slots:
void process()
{
this->isRunning_ = true;
qDebug() << this << "processing started";
for (int i = 0; i < 5; i++)
{
QThread::usleep(1000);
emit this->inProgress();
}
qDebug() << this << "processing finished";
this->isRunning_ = false;
emit this->processingFinished();
}
private:
bool isRunning_;
};
workermanager.h:
#include "worker.h"
class WorkerManager : public QObject
{
Q_OBJECT
public:
explicit WorkerManager(QObject *parent = 0) :
QObject(parent) {}
public slots:
void process()
{
QThread *thread = new QThread();
Worker *worker = new Worker();
connect(thread,SIGNAL(started()),worker,SLOT(process()));
connect(worker,SIGNAL(processingFinished()),this,SLOT(slot1()));
connect(worker,SIGNAL(inProgress()),this,SLOT(slot2()));
worker->moveToThread(thread);
qDebug() << "starting";
thread->start();
QThread::usleep(500);
while(worker->isRunning()) { }
qDebug() << "finished";
}
void slot1() { qDebug() << "slot1"; }
void slot2() { qDebug() << "slot2"; }
};
main.cpp (case 1 - no separate thread for
workerManager
):
#include <QCoreApplication>
#include "workermanager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WorkerManager* workerManager = new WorkerManager;
workerManager->process();
qDebug() << "end";
return a.exec();
}
OUTPUT - both
slot1
andslot2
called ata.exec()
(??? - using main event loop?):
starting
Worker(0x112db20) processing started
Worker(0x112db20) processing finished
finished
end
slot2
slot2
slot2
slot2
slot2
slot1
main.cpp (case 2 -
workerManager
moved to separate thread, but thread not started):
#include <QCoreApplication>
#include "workermanager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WorkerManager* workerManager = new WorkerManager;
QThread *thread = new QThread();
workerManager->moveToThread(thread);
workerManager->process();
qDebug() << "end";
return a.exec();
}
OUTPUT - neither
slot1
norslot2
was called - (??? event loop associated with thread receives signals but since thread was not started slots are not called?):
starting
Worker(0x112db20) processing started
Worker(0x112db20) processing finished
finished
end
main.cpp (case 3 -
workerManager
moved to separate thread, thread started butworkerManager::process()
called viaworkerManager->process()
):
#include <QCoreApplication>
#include "workermanager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WorkerManager* workerManager = new WorkerManager;
QThread *thread = new QThread();
workerManager->moveToThread(thread);
thread->start();
workerManager->process();
qDebug() << "end";
return a.exec();
}
OUTPUT -
slot2
called whileWorker
still executing itsprocess()
(???):
starting
Worker(0x197bb20) processing started
slot2
slot2
slot2
slot2
Worker(0x197bb20) processing finished
finished
end
slot2
slot1
main.cpp (case 4 -
workerManager
moved to separate thread, thread started butworkerManager::process()
called usingstarted()
signal fromthread
):
#include <QCoreApplication>
#include "workermanager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WorkerManager* workerManager = new WorkerManager;
QThread *thread = new QThread();
workerManager->moveToThread(thread);
QObject::connect(thread,SIGNAL(started()),workerManager,SLOT(process()));
thread->start();
qDebug() << "end";
return a.exec();
}
OUTPUT - all events processed after reaching
a.exec()
(???):
end
starting
Worker(0x7f1d700013d0) processing started
Worker(0x7f1d700013d0) processing finished
finished
slot2
slot2
slot2
slot2
slot2
slot1
最佳答案
你得到的所有结果都是完全正确的。我将尝试解释这是如何工作的。
事件循环是 Qt 代码中处理系统和用户事件的内部循环。当您调用 a.exec()
时,主线程的事件循环开始.另一个线程的事件循环默认启动QThread::run
的实现.
当 Qt 决定是时候处理一个事件时,它会执行它的事件处理程序。当事件处理程序工作时,Qt 没有机会处理任何其他事件(除非由 QApplication::processEvents()
或其他一些方法直接给出)。一旦事件处理程序完成,控制流返回到事件循环,Qt 可能会执行另一个处理程序来处理另一个事件。
信号和槽与 Qt 术语中的事件和事件处理程序不同。但是插槽由事件循环处理有点类似。如果您的代码中有控制流(例如在 main
函数中),您可以像任何其他 C++ 函数一样立即执行任何插槽。但是当 Qt 这样做时,它只能从事件循环中做到这一点。需要注意的是,信号总是立即发送,而槽执行可能会延迟。
现在让我们看看在每种情况下会发生什么。
情况1WorkerManager::process
在程序开始时直接执行。新线程开始,Worker::process
在新线程中立即执行。 WorkerManager::process
继续执行直到 Worker 完成,卡住主线程中的所有其他操作(包括槽处理)。后 WorkerManager::process
完成,控制流转到 QApplication::exec
. Qt 建立到另一个线程的连接,接收有关插槽调用的消息并因此调用所有这些消息。
案例二
Qt 默认在该对象所属的线程中执行该对象的槽。主线程不会执行 WorkerManager
的槽因为它属于另一个线程。然而,这个线程永远不会启动。它的事件循环永远不会完成。 slot1
的调用和 slot2
永远留在 Qt 的队列中等待您启动线程。悲剧。
案例3
在这种情况下 WorkerManager::process
在主线程中执行,因为您直接从主线程调用它。同时,WorkerManager
的线程启动。它的事件循环启动并等待事件。 WorkerManager::process
开始 Worker
的线程并执行 Worker::exec
在里面。 Worker
开始向 WorkerManager
发送信号. WorkerManager
的线程几乎立即开始执行适当的插槽。在这一点上似乎很尴尬WorkerManager::slot2
和 WorkerManager::process
是同时执行的。但它完全没问题,至少如果 WorkerManager
是线程安全的。不久之后 Worker
完成,WorkerManager::process
完成并a.exec()
已执行但没有太多处理。
案例四
主要功能刚刚启动 WorkerManager
的线程并立即转到 a.exec()
,导致 end
作为输出中的第一行。 a.exec()
处理某些东西并确保程序执行但不执行 WorkerManager
的插槽,因为它属于另一个线程。 WorkerManager::process
在 WorkerManager
中执行的事件循环中的线程。 Worker
的线程启动并且 Worker::process
开始从 Worker
发送信号的线程到 WorkerManager
的线程。不幸的是后者正忙于执行 WorkerManager::process
.当Worker
完成,WorkerManager::process
也完成和 WorkerManager
的线程立即执行所有排队的插槽。
您代码中最大的问题是 usleep
和无限循环。在使用 Qt 时,您几乎不应该使用它们。据我所知,在 Worker::process
中 sleep 只是一些实际计算的占位符。但是你应该从 WorkerManager
中删除 sleep 和无限循环.使用 WorkerManager::slot1
检测 Worker
的终止。如果您开发 GUI 应用程序,则无需移动 WorkerManager
到另一个线程。它的所有方法(没有 sleep )将快速执行并且不会卡住 GUI。
关于c++ - 在 Qt 中使用多线程时的事件循环和信号槽处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28055749/
我正在使用 Qt 语言学家翻译一个 ui 文件。我使用 lupdate 获取了它的 ts 文件,并翻译了这些单词和短语。现在我想将它添加到我的代码中,但我从它的教程中发现我似乎必须将 tr() 添加到
我想在 Qt Creator 中创建下面的简单控制台应用程序: #include int main(int argc, char* argv[]) { std::cout #include
我想将 libQtGui.so.4 libQtNetwork.so.4 和 libQtCore.so.4 包含在与我的应用程序所在的目录相同的目录中。我如何让 Qt 理解这一点? y 目的是拥有一个使
我有一个充满 QPushButtons 和 QLabels 以及各种其他有趣的 QWidget 的窗口,所有这些都使用各种 QLayout 对象动态布局...而我想做的是偶尔制作一些这些小部件变得不可
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
我想知道 Qt 是否将下面代码的“版本 1”之类的东西放在堆上?在版本 1 中,Qt 会将 dirStuff 放在堆栈上还是堆上?我问是因为我有一种感觉,Java 将所有数据结构放在堆上......不
这个问题是关于 Qt Installer Framework 2.0 版的。 在这一点上,使用 Qt 安装程序框架的人都知道,如果不进行自定义,您根本无法通过安装程序覆盖现有安装。这样做显然是为了解决
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
因为我在我的计算机上安装了 Qt 4.8.4 和 Qt 5.1,所以我遇到了问题。 当只有 Qt 4.8.4 存在时,一切都很好。 当我添加 Qt 5.1 时,这个工作正常,但 Qt 4.8.4 给了
我无法在我的 Ubuntu 12 中安装更多软件包。我尝试了 apt-get install -f ,以及许多其他类似的技巧,但在找到解决方案方面没有进展。 这是属于 Qt 的损坏包: 以下包具有未满
我正在尝试使用 Virtual Box 中的 Ubuntu 机器复制我们目前在物理 Ubuntu 服务器上运行的应用程序。它是一个 QT 应用程序,但在服务器上我们使用 NPM 的 pm2 运行它。安
问题: Qt Creator 是用 Qt Creator 构建的吗? 同样,Qt Designer 是用 Qt Designer 构建的吗? 顺便说一句,为什么有两个 Qt IDE?他们是竞争对手吗?
当我使用 QWidget设计用户界面时,我总是对它的大小属性有点困惑。有size policy , geometry和 hintSize . 我只知道size policy之间的关系和 hintSiz
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我想知道是否有一种很好的方法可以让用户像 LabView 一样创建节点图(有限制)。 像这样的东西: 我见过http://www.pyqtgraph.org/ ,这似乎有类似的东西,我确实打算使用 P
在 Qt 中是否有一种跨平台的方式来获得用户喜欢的固定宽度和比例字体? 例如,在 cocoa 中,有 NSFont *proportional = [NSFont userFontOfSize:12.
我想使用 Qt 和 C++ 制作这样的交互式图表:http://jsxgraph.uni-bayreuth.de/wiki/index.php/Cubic_spline_interpolation 关
我正在编写一个嵌入式设备屏幕的模拟(其中包含主 QWidget 顶部的自定义小部件),虽然屏幕的原始尺寸是 800x600,但我希望能够按比例放大和缩小它拖动窗口的角。如果不使用网格布局和担架(不会向
在下面的示例中,我是否必须从堆中删除对象?如果是的话,怎么办? #include #include #include #include #include int main(int argc,
来自 Web 开发背景,我现在进入 QT 应用程序开发。 使用 QFonts 我已经看到我显然只有两个选择,在 QT 中定义字体大小;按像素大小或点大小。 在制作网页布局时,我习惯于以相对方式定义所有
我是一名优秀的程序员,十分优秀!