有一個想法,一個客戶端,有GUI界面的同時也要向網絡服務器發送本地采集的數據,通過網絡發送數據的接口是同步阻塞的,需要等待服務器響應數據。
如果不采用后台線程的方案,用主UI線程關聯一個定時器QTimer來做定時任務發送,那么GUI界面會由於定時器事件響應的槽函數的阻塞,導致整個GUI的按鈕事件在某些時刻無法及時響應,會有卡頓的情況。
所以,后台需要運行一個后台線程,與主線程分離,並且該后台線程需要關聯一個自己的QTimer,來做定時任務數據采集。
方案其實可以用QThread來做,首先,做一個Task Class:
1 #include <QTimer> 2 #include <QObject> 3 4 class MyTaskClass : public QObject 5 { 6 Q_OBJECT 7 public: 8 explicit MyClass(QObject *parent = 0) 9 { 10 m_task_timer.setInterval(5000); 11 12 connect(&m_task_timer, SIGNAL(timeout()), this, SLOT(dataCollectionSendTask())); 13 14 m_task_timer.start(); 15 } 16 public slots: 17 void dataCollectionSendTask() 18 { 19 //調用網絡接口發送采集完成的數據,發送的服務器 20 } 21 private: 22 QTimer m_task_timer; 23 24 25 };
然后創建一個QThread線程,把整個MyTaskClass類的實例move到線程中就可以了:
1 #include <QtWidgets/QApplication> 2 #include <QThread> 3 #include "MyTaskClass.hpp" 4 5 int main(int argc, char *argv[]) 6 { 7 QApplication a(argc, argv); 8 9 QThread* backgroundThread = new QThread; 10 backgroundThread->start(); 11 12 MyTaskClass *task = new MyTaskClass(); 13 task->moveToThread(backgroundThread); 14 15 MainWindow w; 16 w.show(); 17 return a.exec(); 18 }
以上代碼就不會阻塞GUI線程了。一個后台線程有一個自己的定時器。
references:
https://stackoverflow.com/questions/18958436/how-to-run-a-timer-inside-a-qthread
http://blog.csdn.net/sydnash/article/details/7425947
http://www.cnblogs.com/liushui-sky/p/5833931.html