QT线程问题…某些东西正在拖延GUI响应
QT Threading issues... something is stalling GUI response
我有QT线程问题,不知何故会使主GUI停滞。
回答第一个问题…是的,QThread不是子类化的,并且是以"正确的方式"完成的。
线程是长期运行的(不是"do x然后退出"),它的主循环确实有延迟/睡眠。
线程的主要目的是从其他地方收集数据,组成图像,并通过COM端口传输该图像。
我认为有一些编码区域可能会产生问题。
我使用我自己的"睡眠"功能,因为msleep不可用(仅对QThread私有)。有人能看到下面的代码有什么问题吗?
void SendImageJob::tSleep(int ms)
{
QElapsedTimer timer;
timer.start();
while ((timer.elapsed() < ms) && !abort)
{
QCoreApplication::processEvents();
}
}
第二个可能是问题的是通过信号/插槽发送到/从线程发送的数据量。通过信号发送的图像数据大小约为16KB,以15fps的速度发送。对于排队的连接信号来说,这是否太多了?
我会检查Qt信号队列长度,但我不能找出这是如何做到的?
提前感谢!
您的sleep
代码没有任何问题,只是您根本不需要使用它。在Qt 5中,线程的sleep
方法不再是私有的。在Qt 4中,您可以轻松地绕过它。无论如何,您需要使用这个安全的QThread
包装器来获得真正的RAII优点,因此您不妨在同一个类中公开静态睡眠方法:
class Thread : public QThread {
using QThread::run; // final, no subclassing
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
using QThread::sleep;
using QThread::msleep;
using QThread::usleep;
};
您的部分问题可能是您正在使用阻塞QObject
,这是一个稍微落后的设计。除非你一直在使用阻塞api(比如一个坏了的数据库接口库),否则你的对象应该在任何线程上都能令人满意地执行,包括GUI线程。只有将它移动到一个单独的线程中,才能减少GUI线程的延迟。
合理实现它的一种方法是利用异步:
class Worker : public QObject {
Q_OBJECT
typedef void (Worker::*State)();
QBasicTimer m_timer;
State m_nextState;
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) return;
m_timer.stop();
(this->*m_nextState)();
}
void wait(State state, int ms) {
m_nestState = state;
m_timer.start(this, ms);
}
void state1() {
...
wait(&Worker::state2, 100); // wait 100ms and continue in state2
}
void state2() {
...
}
public:
Worker(QObject * parent = 0) : QObject(parent), m_nextState(&Worker::state1) {
m_timer.start(this, 0);
}
};
如果您可以使用Qt 5和c++ 11 - lambdas来拯救,这样的代码将变得更清晰。您还可以研究QStateMachine
的使用。
更改应用程序的视点也会有所帮助。而不是"在线程中做一些事情",你可以创建你的DataSource
类和移动到QThread
。这个数据源应该负责创建一个帧(通过一个onCreateFrame
插槽),并且可以被一个QTimer
每秒触发15次。
让Qt完成等待:)
简短且仅显示设计的暗示:
QApplication app;
auto datasource = new DataSource(&app);
auto comsender = new ComPort("COM1", &app); // or whatever your class
QTimer fpstimer;
fpstimer.setInterval(1000/15);
check_for_success(QObject::connect(
datasource, DataSource::data,
comsender, ComPort::sendData));
check_for_success(QObject::connect(
&fpstimer, QTimer::timeout,
datasource, DataSource::onCreateFrame));
// make sure everything runs on it's own thread
datasource->moveToThread(new QThread(&app));
comsender->moveToThread(new QThread(&app));
app.exec();
- C++GTKMM gui循环依赖关系
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 当服务中的事件被触发时,如何将响应从服务发送回客户端?
- 我的程序有一个保存配置文件的GUI,如何双击此配置文件以直接加载带有配置数据的GUI?
- 在哪里放置我的函数?进入我的母语 Gui 还是进入我的演示者?
- C++ 信号和插槽不工作:插槽不响应事件
- NodeJs 服务器充斥着 UDP 广播,不发送响应
- C++关于ENUM的问题。我得到的响应比枚举列表大
- 如何在带有 gdb GUI 前端的 ARM gdbserver 的 PC 上执行远程 gdb 会话?
- 应用程序在打开的简历中捕获视频后没有响应
- 在 Gui Win32 中创建子窗口C++
- 使用 cpprest (Casablanca) 返回 PDF 响应
- 如何防止 std::thread 在 QT 中冻结 GUI?
- 为什么当通过 TCP 发送的消息速率增加时,请求-响应消息对的延迟会降低?
- 调试控制台 ChessEngine.exe "used"在另一个应用程序(国际象棋 GUI)中
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- QtConcurrent - 在发布到 UI 线程的数千个结果中保持 GUI 响应
- MFC GUI 自定义控件:如何绘制光标更新以响应鼠标移动?
- Qt QSplitter 和无响应的 GUI (CPU 100%)
- QT线程问题…某些东西正在拖延GUI响应