由于其他线程忙于大循环,QTimer会迟到

时间:2016-12-16 10:32:11

标签: qt signals qthread qtimer qeventloop

环境简介: 我有一个设备运行一个用qt编写的应用程序。它有一个处理数据库操作的主线程(SQlite)和一个用于网络操作的独立线程(通过3G)。 主线程事件循环由QCoreApplication :: exec运行,另一个处理网络操作的线程由QThread :: exec运行。顺便说一句,套接字线程关联性在它启动后会改变(例如moveToThread(socketThreadPtr))

问题简介: 主线程忙于循环,以便从数据库中选择大约10k条记录,该循环大约需要+30秒。在网络线程中有一个15秒的计时器,它必须在每次到期时发送保持活动消息。问题是只有在循环完成后才会执行timeout()信号的插槽。

到目前为止建立的解决方案(但不满意): 如果我在选择记录的循环中调用QCoreApplication :: processEvents,问题就解决了,但我想知道是否存在解决方案而不是这种解决方法。

注: 发出保持活动消息的命令的定时器,信号和插槽当前在主线程中处理(但是读/写发生在网络线程中)。另外,我在网络线程上移动了计时器,但是我得到了与主线程相同的结果。

2 个答案:

答案 0 :(得分:1)

你必须在你的网络线程中创建计时器,也许Qtimer是网络线程的成员,所以网络线程将构建在其子线程的主线程和线程关联中 设置为主线程,接下来你已经将网络线程移动到新的Qthread,但是Qtimer呢?它仍然存在于主线程中(除非您明确定义网络类作为它的父级,因此您说moveToThread将影响对象的子级以及Qtimer)

Qtimer应该在网络线程中构建,您可以在其中一个网络线程插槽中构建一个新的Qtimer并将其连接到Qthread :: start信号。因此,通过调用Qthrad的start方法,您的插槽将在新线程上执行,Qtimer将分别在该线程上构建。

答案 1 :(得分:0)

这样的东西实际上应该在你的专用线程中创建套接字和定时器,因为你的主线程是服务器,客户端应该在线程中处理。否则,只需在初始化函数中使用QTcpSocket::connectToHost()QTcpServer:::bind()

Mainthread:

auto t = new QThread();
t->start();
auto o = new MyThreadObject();
o.moveToThread(t);
o.setDescriptor(socketDesc);
QMetaObject::invokeMethod(o, "initialize", Qt::QueuedConnection);

MyThreadObject:

class MyThreadObject : public QObject
{
  Q_OBJECT
public:
  MyThreadObject(){...};
  void setDescriptor(qintptr socketdescriptor)
  {
    m_desc = socketdescriptor;
  }
public slots:
  void initialize()
  {
    m_tcpSocket = new QTcpSocket();
    m_tcpSocket->setSocketDescriptor(m_desc);
    //socket configuration
    m_timer = new QTimer();
    //timer configuration
    m_timer->start();
  }
private:
  QTcpSocket* m_tcpSocket;
  QTimer* m_timer;
  qintptr m_desc;
}