QT线程问题...的东西是停止GUI响应 [英] QT Threading issues... something is stalling GUI response

查看:169
本文介绍了QT线程问题...的东西是停止GUI响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题的QT线程以某种方式停止主GUI。



回答第一个问题...是的,QThread不是子类, 正确的方式。



线程是长期运行的(不是do x then exit),它的主循环有延迟/睡眠。 / p>

线程的主要目的是从其他地方收集数据,组合图像,并通过COM端口传输图像。



我使用自己的sleep函数,因为msleep不可用(仅适用于QThread) 。
任何人都看不到下面的代码有什么错误?

  void SendImageJob :: tSleep(int ms)
{
QElapsedTimer timer;
timer.start();
while((timer.elapsed()< ms)&&!abort)
{
QCoreApplication :: processEvents();
}
}

第二件事可能是一个问题通过信号/时隙发送到线程/从线程发送的数据量。
通过信号发送的图像数据大小约为16KB,并以15fps发送。
这对队列连接信号来说太多了?



我会检查Qt信号队列长度,但我不知道如何做到这一点?



提前感谢!

解决方案

code> sleep 代码,除了你不需要使用它。在Qt 5中,线程的 sleep 方法不再是私有的了。在Qt 4中,你可以轻而易举地解决它。你需要使用这个安全的 QThread 包装器来获得真正的RAII好处,所以你可以在同一个类中公开静态睡眠方法:

 类线程:public QThread {
using QThread :: run; // final,no subclassing
public:
Thread(QObject * parent = 0):QThread(parent){}
〜Thread(){quit等待(); }
using QThread :: sleep;
使用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); //等待100ms并继续在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 的使用。



在16fps处推送16kbytes无关。


I'm having issues with QT threading somehow stalling the main GUI.

To answer the first question... yes, QThread is not subclassed, and is done the "right way".

The thread is run long-term (not a "do x then exit"), and it's main loop does have delays/sleeps.

The threads main purpose is to collect data from elsewhere, compose an image, and transmit that image over a COM port.

There are coding areas that i think could be creating the problem.

Im using my own "sleep" function as msleep is not available (private to QThread only). Can anyone see anything wrong with the code below?

void SendImageJob::tSleep(int ms)
{
  QElapsedTimer   timer;
  timer.start();
  while ((timer.elapsed() < ms) && !abort)
  {
      QCoreApplication::processEvents();
  }
}

The second thing that may be an issue is in the amount of data being sent to/from the thread via signals/slots. The image data being sent via a signal is about 16KB in size, and is sent at 15fps. Is this too much for queued connection signals to handle?

I would check the Qt signal queue length, but i cant find out how this can be done?

Thanks in advance!

解决方案

There's nothing wrong with your sleep code except that you don't need to use it at all. In Qt 5, thread's sleep methods aren't private anymore. In Qt 4, you can trivially work around it. You need to use this safe QThread wrapper anyway for true RAII goodness, so you may as well expose the static sleep methods in the same class:

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;
};

Part of your problem may be that you're using a blocking QObject, and that's a slightly backward design. Unless you're stuck using blocking APIs (say a broken database interface library), your object should perform satisfactorily on any thread, including the GUI thread. You only move it to a separate thread to decrease the GUI thread's latency.

One way to sanely implement it is to leverage asynchrony:

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);
  }
};

Such code becomes cleaner if you can use Qt 5 and C++11 - lambdas to the rescue. You can also investigate the use of QStateMachine.

Pushing 16kbytes at 16fps is nothing.

这篇关于QT线程问题...的东西是停止GUI响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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