QT Threading issues… something is stalling GUI response

陌路散爱 提交于 2019-12-25 03:55:44

问题


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!


回答1:


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.




回答2:


Changing your application's viewpoint could also help. Instead of 'doing something in a thread', you can create your DataSource class and move it to a QThread. This data source should be responsible to create a frame (through an onCreateFrame slot), and can be triggered by a QTimer 15 times per second.

Let Qt do the waiting :)

Brief and only to show a hint of a design:

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

Hope this might help.



来源:https://stackoverflow.com/questions/24864594/qt-threading-issues-something-is-stalling-gui-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!