在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Qt中的三個exec之間有什么聯(lián)系

嵌入式小生 ? 來源:嵌入式小生 ? 2023-03-06 09:44 ? 次閱讀

一、導(dǎo)讀

在Qt中,常見到三個exec,第一個是QApplication::exec(),第二個是QEventLoop::exec,第三個是QThread::exec()。本文從源碼角度來看看這三個exec()。

QApplication::exec()是QApplication類下的一個靜態(tài)成員函數(shù),該函數(shù)用于進入主事件循環(huán)。

QEventLoop::exec是QEventLoop類下的一個公共成員函數(shù),用于進入主事件循環(huán)。

QThread::exec()是QThread類下的一個受保護的成員函數(shù),也是用于進入事件循環(huán)。

都是進入事件循環(huán),他們之間有什么聯(lián)系呢,接著后面的分析。

二、QApplication::exec()

在實際開發(fā)中,必須調(diào)用QApplication::exec()來啟動事件處理,主事件循環(huán)會從窗口系統(tǒng)接收事件,并將這些事件分派給應(yīng)用程序小部件。在調(diào)用exec()之前不能發(fā)生任何用戶交互,但是存在一種特殊的情況:QMessageBox這樣的模態(tài)小部件可以在調(diào)用exec()之前使用,因為模態(tài)小部件會調(diào)用exec()來啟動本地事件循環(huán)。

從源碼角度,QApplication::exec()會調(diào)用QGuiApplication::exec(),QGuiApplication::exec()會調(diào)用QCoreApplication::exec():

intQCoreApplication::exec()
{
//檢查exec實例
if(!QCoreApplicationPrivate::checkInstance("exec"))
return-1;

//獲取線程數(shù)據(jù)QThreadData
QThreadData*threadData=self->d_func()->threadData;

//檢查該函數(shù)的調(diào)用是否在主線程中,如果不是,則返回。
if(threadData!=QThreadData::current()){
qWarning("%s:Mustbecalledfromthemainthread",self->metaObject()->className());
return-1;
}
//檢查是否存在事件循環(huán),如果存在,則返回,否則繼續(xù)后續(xù)操作。
if(!threadData->eventLoops.isEmpty()){
qWarning("QCoreApplication:Theeventloopisalreadyrunning");
return-1;
}

threadData->quitNow=false;
//創(chuàng)建QEventLoop事件循環(huán)對象
QEventLoopeventLoop;
self->d_func()->in_exec=true;
self->d_func()->aboutToQuitEmitted=false;
//啟動事件循環(huán)
intreturnCode=eventLoop.exec();
threadData->quitNow=false;

if(self)
self->d_func()->execCleanup();

returnreturnCode;
}

從上述源碼可見,QApplication的exec()經(jīng)過層層調(diào)用,最終是使用QEventLoop實現(xiàn)事件循環(huán)。

QApplication::exec()用于啟動應(yīng)用程序的事件循環(huán),讓應(yīng)用程序能得以啟動運行并接收事件。

『備注,執(zhí)行應(yīng)用清理的優(yōu)雅方式』:

建議將清理代碼連接到aboutToQuit()信號,而不是放在應(yīng)用程序的main()函數(shù)中。這是因為,在某些平臺上,QApplication::exec()調(diào)用可能不會返回。例如,在Windows平臺上,當(dāng)用戶注銷時,系統(tǒng)會在Qt關(guān)閉所有頂級窗口后終止該進程。因此,不能保證應(yīng)用程序有足夠的時間退出事件循環(huán),并在QApplication::exec()調(diào)用之后,即在main()函數(shù)的末尾執(zhí)行代碼。

在QCoreApplication::exec()函數(shù)實現(xiàn)中的這幾行代碼:

if(threadData!=QThreadData::current()){
qWarning("%s:Mustbecalledfromthemainthread",self->metaObject()->className());
return-1;
}

引發(fā)出另一個有趣的知識點,那就是:在Qt多線程開發(fā)中,需要注意不要阻塞GUI線程,那么哪個是GUI線程呢?從上述源碼可以明確知道:QApplication a(argc, argv);所在線程就是GUI線程。

三、QThread::exec()

在多線程應(yīng)用設(shè)計中,QThread::exec()用于為當(dāng)前線程啟動一個新的事件循環(huán),為存在于該線程中的對象交付事件。在源碼中,QThread::exec()實現(xiàn)如下:

intQThread::exec()
{
Q_D(QThread);
QMutexLockerlocker(&d->mutex);
d->data->quitNow=false;
if(d->exited){
d->exited=false;
returnd->returnCode;
}
locker.unlock();
//創(chuàng)建QEventLoop事件循環(huán)。
QEventLoopeventLoop;
intreturnCode=eventLoop.exec();

locker.relock();
d->exited=false;
d->returnCode=-1;
returnreturnCode;
}

從源碼角度,也可見QThread::exec()實現(xiàn)中也調(diào)用到QEventLoop的exec()。

四、QEventLoop::exec()

QEventLoop::exec()用于進入主事件循環(huán)并等待直到exit()被調(diào)用。在調(diào)用該函數(shù)時需要傳入一個flags,如果指定了標志,則只處理標志允許的類型的事件,Qt中支持以下幾種標志:

序號 標志類型 描述
1 QEventLoop::AllEvents 所有事件
2 QEventLoop::ExcludeUserInputEvents 不處理用戶輸入事件,例如ButtonPress和KeyPress。
3 QEventLoop::ExcludeSocketNotifiers 不要處理套接字通知事件。
4 QEventLoop::WaitForMoreEvents 如果沒有可用的掛起事件,則等待事件。

注意,沒有被傳遞的事件不會被丟棄,這些事件將在下次傳入不過濾事件的標志調(diào)用procesvents()時被傳遞。

從源碼角度,QEventLoop::exec()實現(xiàn)如下:

intQEventLoop::exec(ProcessEventsFlagsflags)
{
Q_D(QEventLoop);
autothreadData=d->threadData.loadRelaxed();

//weneedtoprotectfromraceconditionwithQThread::exit
QMutexLockerlocker(&static_cast(QObjectPrivate::get(threadData->thread.loadAcquire()))->mutex);
if(threadData->quitNow)
return-1;

if(d->inExec){
qWarning("QEventLoop:instance%phasalreadycalledexec()",this);
return-1;
}

structLoopReference{
QEventLoopPrivate*d;
QMutexLocker&locker;

boolexceptionCaught;
LoopReference(QEventLoopPrivate*d,QMutexLocker&locker):d(d),locker(locker),exceptionCaught(true)
{
d->inExec=true;
d->exit.storeRelease(false);

autothreadData=d->threadData.loadRelaxed();
++threadData->loopLevel;
threadData->eventLoops.push(d->q_func());

locker.unlock();
}

~LoopReference()
{
if(exceptionCaught){
qWarning("Qthascaughtanexceptionthrownfromaneventhandler.Throwing
"
"exceptionsfromaneventhandlerisnotsupportedinQt.
"
"YoumustnotletanyexceptionwhatsoeverpropagatethroughQtcode.
"
"Ifthatisnotpossible,inQt5youmustatleastreimplement
"
"QCoreApplication::notify()andcatchallexceptionsthere.
");
}
locker.relock();
autothreadData=d->threadData.loadRelaxed();
QEventLoop*eventLoop=threadData->eventLoops.pop();
Q_ASSERT_X(eventLoop==d->q_func(),"QEventLoop::exec()","internalerror");
Q_UNUSED(eventLoop);//--releasewarning
d->inExec=false;
--threadData->loopLevel;
}
};
LoopReferenceref(d,locker);

//當(dāng)進入一個新的事件循環(huán)時,刪除已發(fā)布的exit事件
QCoreApplication*app=QCoreApplication::instance();
if(app&&app->thread()==thread())
QCoreApplication::removePostedEvents(app,QEvent::Quit);

#ifdefQ_OS_WASM
//Partialsupportfornestedeventloops:MaketheruntimethrowaJavaSrcript
//exception,whichreturnscontroltothebrowserwhilepreservingtheC++stack.
//Eventprocessingthencontinuesasnormal.Thesleepcallbelowneverreturns.
//QTBUG-70185
if(threadData->loopLevel>1)
emscripten_sleep(1);
#endif

while(!d->exit.loadAcquire())
processEvents(flags|WaitForMoreEvents|EventLoopExec);

ref.exceptionCaught=false;
returnd->returnCode.loadRelaxed();
}

從上述源碼可知,QEventLoop::exec()本質(zhì)會調(diào)用 processEvents()分發(fā)事件。 processEvents()實現(xiàn)如下:

cc77bc0a-bb5e-11ed-bfe3-dac502259ad0.png

從上圖所示代碼中,會調(diào)用QAbstractEventDispatcher::processEvents()實現(xiàn)事件分發(fā)。QAbstractEventDispatcher類提供了一個管理Qt事件隊列的接口,它從窗口系統(tǒng)和其他地方接收事件。然后它將這些事件發(fā)送到QCoreApplication或QApplication實例進行處理和交付。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3825

    瀏覽量

    82558
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    668

    瀏覽量

    30202
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    279

    瀏覽量

    20341
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4374

    瀏覽量

    64383
  • Qt
    Qt
    +關(guān)注

    關(guān)注

    1

    文章

    314

    瀏覽量

    38889

原文標題:Qt這三個exec,傻傻分不清!

文章出處:【微信號:嵌入式小生,微信公眾號:嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦
    熱點推薦

    proteussounder speaker buzzer 三個什么不同

    proteussounder speaker buzzer 三個什么不同,之前就發(fā)現(xiàn)了,但是一直很模糊,求助啊。。。。
    發(fā)表于 05-20 18:18

    labview如何實現(xiàn)三個事件互鎖?

    labview如何實現(xiàn)三個事件互鎖?即三個布爾量只允許一輸出為TRUE,剩下兩FALSE。有人能指點小弟一二嗎
    發(fā)表于 10-26 14:25

    Qt學(xué)習(xí)常用的類

    學(xué)的原因所在)。其實在QT你會發(fā)現(xiàn)有QApplication和return *.exec()是必須有的這也是QT運行時的機制, 當(dāng)執(zhí)行到 *.ex
    發(fā)表于 10-18 09:47

    如何用C語言編寫圖上的三個方波的編程,能否解讀下三個方波之間聯(lián)系

    如何用C語言編寫圖上的三個方波的編程,能否解讀下三個方波之間聯(lián)系,老師給的方波,表示沒看懂,不知如何從何下手
    發(fā)表于 12-05 16:02

    請問這之間什么聯(lián)系

    工程師朋友,你好:我是新手,想問升壓型DC-DC芯片的開關(guān)電流Isw、輸出電流Iout和芯片的耗電,之間什么聯(lián)系
    發(fā)表于 07-04 08:33

    如何鑒別可控硅的三個

    如何鑒別可控硅的三個極 鑒別可控硅三個極的方法很簡單,根據(jù)P-N結(jié)的原理,只要用萬用表測量一下三個之間的電阻值就可以。
    發(fā)表于 12-02 08:34 ?913次閱讀

    鑒別可控硅三個極的方法

    鑒別可控硅三個極的方法 鑒別可控硅三個極的方法很簡單,根據(jù)P-N結(jié)的原理,只要用萬用表測量一下三個之間的電
    發(fā)表于 01-14 16:20 ?1303次閱讀

    實施智能制造需要考慮三個支點

    筆者在《論智能制造》系列的“論智能制造的三個階段”,談到了對三個階段的基本認識。而如何實施智能制造,則需要考慮智能制造的三個支點:產(chǎn)品、
    發(fā)表于 11-06 15:31 ?1016次閱讀

    閑聊HDMI、DVI、VGA三個接口的區(qū)別及聯(lián)系

    今天來聊聊一篇關(guān)于dvi接口:HDMI、DVI、VGA接口什么聯(lián)系的文章,現(xiàn)在就為大家來簡單介紹下dvi接口:HDMI、DVI、VGA接口什么聯(lián)系,希望對各位小伙伴們有所幫助。
    發(fā)表于 07-17 10:55 ?7382次閱讀

    談?wù)凱CBA、SMT、PCB之間區(qū)別與聯(lián)系

    很多剛開始接觸電子行業(yè)的人,常常會被PCBA、SMT、PCB這三個給弄混,很難分清楚它們之間的區(qū)別和聯(lián)系,接下來眾焱電子就通過通俗易懂的語言來談?wù)凱CBA、SMT、PCB
    的頭像 發(fā)表于 03-19 09:31 ?3.1w次閱讀

    Qt Designer、Qt Quick Designer和Qt Creator應(yīng)用程序什么區(qū)別?

    Designer與之類似,只是用于構(gòu)建QML GUI,而兩者都內(nèi)置在Qt Creator。 我們通過使用它們的方法來解釋這些工具之間的區(qū)
    的頭像 發(fā)表于 03-17 09:40 ?7580次閱讀

    mosfet的三個電極怎么區(qū)分 mos管三個極電壓關(guān)系

    MOSFET(金屬氧化物半導(dǎo)體場效應(yīng)晶體管)三個主要電極,分別是柵極(Gate)、漏極(Source)和源極(Drain)。這三個電極的區(qū)分方法如下
    的頭像 發(fā)表于 09-18 12:42 ?3.9w次閱讀

    docker exec命令的使用方法

    Docker是一種開源的容器化平臺,可以讓開發(fā)人員在容器打包和運行應(yīng)用程序。它提供了一種快速、可靠和一致的方式來構(gòu)建、部署和運行應(yīng)用程序。Docker exec命令是Docker提供的一非常
    的頭像 發(fā)表于 11-23 09:33 ?2217次閱讀

    晶體管的三個極的電壓關(guān)系大小

    晶體管是一種半導(dǎo)體器件,用于放大電信號、開關(guān)電路和邏輯運算等。它是現(xiàn)代電子技術(shù)和計算機科學(xué)的核心之一。在晶體管三個電極:基極、發(fā)射極和集電極。這三個電極的電壓
    的頭像 發(fā)表于 12-20 14:50 ?8418次閱讀

    微波測量的三個基本參量是什么

    微波測量是電子工程領(lǐng)域中的一重要分支,它涉及到對微波信號的頻率、幅度、相位等參數(shù)的測量。在微波測量三個基本參量:頻率、幅度和相位。這三個
    的頭像 發(fā)表于 05-28 14:46 ?2067次閱讀
    主站蜘蛛池模板: 三级欧美在线 | 免费人成在线观看网站品爱网日本 | 天天激情站 | 美女好紧好大好爽12p | 男子扒开美女尿口做羞羞的事 | 国产午夜影院 | 性色影院 | 夜夜夜夜夜操 | 国产精品久久久久久久人热 | 午夜影院0606免费 | 日本黄色大片网站 | 中文字幕亚洲一区二区va在线 | 高清视频在线播放 | 精品久久久久久中文字幕欧美 | 久久伊人精品青青草原高清 | 色综合88| 亚洲日韩图片专区第1页 | bt天堂在线最新版www | www深夜视频在线观看高清 | 国产在线麻豆自在拍91精品 | 天天做.天天爱.天天综合网 | 欧美性狂猛xxxxxbbbbb | 男男h文小说阅 | 美女被艹视频网站 | 色综合久久久高清综合久久久 | 奇米色婷婷 | caoporn97人人做人人爱最新 | 欧美色人阁 | 青草91 | 四虎国产 | 色视频www在线播放国产人成 | 亚洲欧美在线一区 | 最近2018年中文字幕大全一 | 男女交性视频免费 | 欧美黄色片免费 | 免费看美女毛片 | 天天干网址 | 国产99久久九九精品免费 | 啪啪啦资源站永久 | 大蕉久久伊人中文字幕 | 色综合久久天天综合观看 |