Qt:工作线程和 GUI 事件之间的关系
Qt: The relation between Worker thread and GUI Events
我有一个普通的GUI线程(主窗口),想将一个工作线程附加到它。Worker 线程将被实例化,移动到它自己的线程,然后触发以独立运行,运行消息传递例程(非阻塞)。
这是创建工作线程的位置:
void MainWindow::on_connectButton_clicked()
{
Worker* workwork;
workwork= new Worker();
connect(workwork,SIGNAL(invokeTestResultsUpdate(int,quint8)),
this,SLOT(updateTestResults(int,quint8)),Qt::QueuedConnection);
connect(this,SIGNAL(emitInit()),workwork,SLOT(init()));
workwork->startBC();
}
这是工作线程开始的地方:
void Worker::startBC()
{
t1553 = new QThread();
this->moveToThread(t1553);
connect(t1553,SIGNAL(started()),this,SLOT(run1553Process()));
t1553->start();
}
关于新线程的事件队列,我在这里有两个问题:
第一个也是小问题是,虽然我可以接收来自 Worker 线程的信号(即:invokeTestResultsUpdate
),但我无法通过从MainWindow
发出emitInit
信号来调用init
方法。除非我直接调用它或通过Qt::DirectConnection
连接它,否则它不会触发。为什么会这样?因为我必须显式启动工作线程自己的消息循环?还是其他我不知道的事情?(即使我尝试了,我真的无法理解线程/事件循环/信号槽机制的概念以及彼此之间的关系。我也欢迎任何新的视角。
第二个也是更晦涩的问题是:run1553process
方法做一些繁重的工作。我所说的繁重工作是指非常高的数据率。有一个循环正在运行,我尝试在设备(实时)到达缓冲区后立即接收流出的数据,主要使用extern
API 函数。然后在每次收到消息时向 GUI 抛出上述invokeTestResultsUpdate
信号,更新消息编号框。仅此而已。
我正在经历的事情很奇怪;通常消息传递例程基本上不受阻碍,但是当我调整主窗口的大小、移动它或隐藏/显示窗口时,Worker 线程会跳过许多消息。而且调整大小的操作真的很慢(响应不是很快)。这真的让我患上了癌症。
(注意:我之前尝试过对QThread进行子类化,但它并没有缓解这个问题。
我一直在阅读所有"线程亲和性"主题并尝试应用它们,但它的行为仍然像在某些时候被 GUI 线程的事件以某种方式打断。我可以理解 MainWindow 的麻烦,因为队列中有许多要执行的消息(调用的插槽和 GUI 事件)。但是我看不出为什么后台线程会受到 GUI 事件的影响。我真的需要一个非常强大且不受阻碍的消息例程,单独运行,发射并忘记信号,并且不在乎任何事情。
我现在真的很渴望任何帮助,所以任何一点信息对我都很有用。请不要犹豫,提出想法。
TL;DR:定期在run1553process
内呼叫QCoreApplication::processEvents();
。
完整解释: 来自主线程的信号被放入队列中,并在第二个线程中的事件循环获得控制权后执行。在实现中,线程启动后立即调用run1553Process
。在手动调用该函数或QCoreApplication::processEvents
之前,控件不会返回到事件循环,因此信号将坐在那里等待事件循环拾取它们。
附言 您在上面的代码中泄漏了工作线程和线程
附言 来自设备的数据流通常提供异步 API,而不必无限期地轮询它们
我终于找到了问题所在。
关键错误是将QThread的内置信号连接到start()
插槽run1553Process()
。我认为这是用这种方法代替run()
,并期望一切都好。但这会导致实际的run()
方法被阻塞,从而阻止事件循环启动。
如qthread.cpp所述:
void QThread::run()
{
(void) exec();
}
为了解决这个问题,我没有触摸原始的start()
信号,而是将另一个信号独立连接到我的run1553Process()
。首先正常启动线程,允许事件循环启动,然后触发我的其他信号。做到了,现在我的 worker 可以接收所有消息。
我想现在我更好地理解了线程和事件之间的关系。
顺便说一下,这个解决方案并没有完全解决消息跳过问题,但我觉得这是由另一个因素引起的(比如我的消息阅读实现)。
谢谢大家的想法。我希望这个解决方案能帮助其他像我这样的穷人。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- Android NDK传感器向事件队列报告奇怪的间隔
- 在cuda线程之间共享大量常量数据
- 在c代码之间共享数据的最佳方式
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 大小相等但成员数量不同的结构之间的性能差异
- 从文本文件中读取时钟时间和事件时间并进行处理
- Qt:工作线程和 GUI 事件之间的关系
- 基于两个程序之间的事件触发器访问数据(内存)
- 服务和用户模式进程之间的共享全局事件不起作用
- 窗口之间的事件
- Qt 中两个线程之间的事件同步
- 两个事件之间的计时持续时间
- 管理Win32应用程序和QWinMigrate之间的键盘事件
- 同步两个线程,在彼此之间传递事件
- c++和Objective C之间的事件处理