一、問題的來源與分析
首先,我們要知道 “為什么Qt Gui 會(huì)停止響應(yīng)?”。簡明扼要的說就是:長時(shí)間的密集處理或等待阻塞了Qt的事件循環(huán),應(yīng)用程序不能響應(yīng)來自窗口系統(tǒng)的事件請求(《C++ Gui Qt4》 P135中有描述)。 那么多長算長呢?一秒鐘算長,兩秒鐘太長。
其次,“ 何種情形下會(huì)發(fā)生該問題? ”??煞譃閮煞N情形:
第一,長時(shí)間按順序執(zhí)行的密集運(yùn)算,全部計(jì)算結(jié)束后才能繼續(xù)執(zhí)行,如快速傅立葉變換。
第二,“ 觸發(fā) ”了某項(xiàng)操作,該操作完成后才能進(jìn)行“ 下一步 ”, 所以這里描述的是異步操作,如保存文件操作,服務(wù)器等待連接、網(wǎng)絡(luò)下載等。詳細(xì)見附注(1).
私以為兩種情形并無明顯的概念上的區(qū)分,本質(zhì)是一樣的,但兩種情形有不同的處理方法,特別是第二種情形, 在Qt框架下 ,用Qt的信號和槽機(jī)制往往可以解決阻塞問題,如QTcpServer::newConnection信號通知連接的到來,QIODevice::bytesWritten()與 QIODevice::readyRead()通知文件的讀寫,它們都是以非阻塞的形式實(shí)現(xiàn)相關(guān)功能的利器。 而第一種情形,不僅所有的事件循環(huán)停止了,信號和槽也暫時(shí)被忽視。我們將針對以上兩種情形尋找解決方案。
最后,我們考慮是否可以把這個(gè)造成 Qt Gui 停止響應(yīng)的罪魁禍?zhǔn)状笮栋藟K,即把他拆分成一個(gè)個(gè)小塊,如果可以拆分,那么每塊之間是依賴還是獨(dú)立,如果獨(dú)立那問題好辦,放在不同的位置獨(dú)立運(yùn)作,否則,我們只能同步的執(zhí)行,而最差的結(jié)果是——根本無法拆分??!
總之,考慮以上信息差異,執(zhí)行不同的解決方案。
二、解決方案
Manual event processing(人工執(zhí)行事件)
保持事件循環(huán)有一種最基本的方法——讓程序去處理 懸掛事件好了 ,處理完了再回來繼續(xù)我的后續(xù)運(yùn)算,要做到這一點(diǎn),就要在我的運(yùn)算代碼中間加上處理事件的代碼,這句代碼就是 QCoreApplication::processEvents();,只要該句代碼能夠周期性的被執(zhí)行,就能保持Qt Gui的響應(yīng)。
//代碼來源于上述鏈接所指向文章