QT5學習::(轉)異步函數轉爲同步函數的方法(即阻塞函數,等待異步或回調函數完成)

在QT中,一般推薦使用異步函數。除了異步函數的非阻塞特性外,QT的Signal/Slot特性在異步函數中可以得到充分的發揮。因此,在QT中,很多API的設計都是使用非阻塞的異步函數作爲API,然後執行結果使用Signal返回。用戶執行API後使用slot函數接收反饋結果。

但是在很多場景下,我們的確可能需要同步函數。也就是說函數在返回執行結果之前必須阻塞,調用函數後必須得到相應的執行結果。這時候,對於大量使用signal/slot的QT程序來說,經常需要將一個異步函數轉變爲同步函數。具體的轉換做法如下。

例如

  • 一個異步的login函數:
  • void login(const QString& username, const QString& password);
  • 返回值使用signal通知:
  • OnLoginStatusChanged();

 下面就是這個異步函數的同步版本:

int loginSync(const QString& username, const QString& password)
{
  int timeout = 30 * 1000; //超時時間設置
  QTimer t;
  QEventLoop q;
  t.setSingleShot(true);
  connect(&t, SIGNAL(timeout()), &q, SLOT(quit()));  //異步調用超時退出
  connect(this, SIGNAL(OnLoginStatusChanged()), &q, SLOT(quit()));  //異步調用完成退出
  Login(username, password);   //調用異步函數
  t.start(timeout); 
  q.exec();
   
  //以下可以根據異步函數的返回結果進行進一步操作並返回函數結果。
  
  。。。。。。
}

需要注意的是,EventLoop的ProcessEvent實際上封裝的是QAbstractEventDispatcher::processEvents。

QT幫助文件中有這樣的描述:
An event dispatcher receives events from the window system and other sources. It then sends them to the   

 QCoreApplication orQApplication instance for processing and delivery. QAbstractEventDispatcher provides fine-grained control over event delivery.

也就是說,使用QAbstractEvent,或者說使用EventLoop,需要有QCoreApplication或者QApplication的存在。

對於GUI程序,這一點不是問題。問題在於對於很多consoleUI命令行程序,很多時候我們並不創建QCoreApplication或者QApplication對象。這樣的場景下Eventloop自然無法正常使用。

因此,如果是在命令行中調用一個用這種方式封裝的同步函數,必須有一個QCoreApplicaion或者QApplication對象存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章