1. 程式人生 > >Qt ------ 主事件循環與 QEventLoop

Qt ------ 主事件循環與 QEventLoop

man fin 等待 obj box cat tail 狀態 font

1、事件循環一般用exec()函數開啟。QApplicaion::exec()、QMessageBox::exec()都是事件循環。其中前者又被稱為主事件循環。

事件循環首先是一個無限“循環”,程序在exec()裏面無限循環,能讓跟在exec()後面的代碼得不到運行機會,直至程序從exec()跳出。從exec()跳出時,事件循環即被終止。QEventLoop::quit()能夠終止事件循環。

其次,之所以被稱為“事件”循環,是因為它能接收事件,並處理之。當事件太多而不能馬上處理完的時候,待處理事件被放在一個“隊列”裏,稱為“事件循環隊列”。當事件循環處理完一個事件後,就從“事件循環隊列”中取出下一個事件處理之。當事件循環隊列為空的時候,它和一個啥事也不做的永真循環有點類似,但是和永真循環不同的是,事件循環不會大量占用CPU資源。

事件循環的本質就是以隊列的方式再次分配線程時間片。

2、事件循環是可以嵌套的,一層套一層,子層的事件循環執行exec()的時候,父層事件循環就處於中斷狀態;當子層事件循環跳出exec()後,父層事件循環才能繼續循環下去。

另外,子層事件循環具有父層事件循環的幾乎所有功能。Qt會把事件送到當前生效的那個事件循環隊列中去,其中包括Gui的各種事件。所以用戶在主線程中執行各種exec()(如QMessageBox::exec(),QEventLoop::exec())的時候,雖然這些exec()打斷了main()中的QApplication::exec(),但是Gui界面仍然能夠正常響應。

3、如果某個子事件循環仍然有效,但其父循環被強制跳出,此時父循環不會立即執行跳出,而是等待子事件循環跳出後,父循環才會跳出。
4、當GUI主線程中的某個函數,比如NETWORK的某個函數為非阻塞,比如下面的例子:

[cpp] view plain copy
  1. 1: QNetworkAccessManager qnam;
  2. 2: QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
  3. 3: QEventLoop loop;
  4. 4: QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
  5. 5: loop.exec();


get函數為非阻塞,立即返回,但是我想等在這裏直至收到真正的數據,這裏用一個局部的循環,等待事件完成後關閉局部循環。

Qt ------ 主事件循環與 QEventLoop