QT中的多執行緒 與主線程通訊

2021-06-22 00:09:01 字數 2814 閱讀 6627

今天回想研究生期間做的專案,用到了qt的多執行緒通訊,當時一點都不懂,就這照貓畫虎地寫,如今因為上次面試中問到了,覺得得好好準備下:

主線程可以通過建立 qthread 子類物件開啟乙個新的執行緒,如果這些執行緒間需要相互通訊,它們可以使用共享變數,同時使用 mutexes,read-write locks,semaphores 或者 wait conditions 一些方法保持共享變數訪問的同步性。但是由於這些技術可能鎖定 event loop,同時還會凍結使用者介面,所以其中沒有乙個能完成與主線程之間的通訊。

完成第二線程(secondary thread)與主線程之間的通訊的方法是:跨執行緒間的 signal-slot 連線。signal 一旦發出,其對應的 slot 函式便立即執行,這種連線是一種同步的機制。

但是當我們將不同執行緒中的物件連線在一起時,這種 signal-slot 通訊機制變得「不同步」(asynchronous)。signal-slot 機制的底層實現是傳遞乙個 event,然後 slot 由 receiver 物件所在的執行緒中的 event loop 呼叫。預設情況下,乙個 qobject 物件存在於建立它的執行緒中,但是任何時刻,呼叫 qobject : : movetothread( ) 函式可以改變這種關係。

當時我們的程式中其實有兩個大類,乙個是transaction類,乙個是transaction thread類,可以看到transaction是個抽象類,裡面的純虛函式execute雖然在子類的實現中都是空的,但是目的就是為了讓transaction成為乙個抽象類,

transaction類:

class transaction 

virtual void execute() = 0;

int gettransactid();

protected:

int transactid;

};class logintransaction: public transaction ;

在cpp檔案中對logintransaction的建構函式和必須實現的介面做定義(雖然是空的。。。)

int transaction::gettransactid() 

logintransaction::logintransaction()

void logintransaction::execute()

然後在transaction tread類中,相當於第二個執行緒,通過single-slot向主線程傳送訊號。

transactiontread.h檔案

class transactionthread: public qthread 

transactionthread::~transactionthread()

wait();

}void transactionthread::addtransaction(transaction *tr)

void transactionthread::run()

processtransact(tr);

//

// if (tr->gettransactid() != tr_added || )

// delete tr; }}

void transactionthread::processtransact(transaction *tr)

}void transactionthread::processtrloginfail(transaction *tr)

void transactionthread::processtrlogin(transaction *tr)

呼叫 qthread : : start( ) 開啟將要執行 transaction 的執行緒。在析構函式中,清空佇列,將乙個特殊的 endtransaction 加入佇列。喚醒執行緒,並使用 qthread : : wait( ) 等待執行緒結束。如果沒有 wait( ),當其它的執行緒訪問類中的成員變數時,程式有可能崩潰。 在析構函式中,qmutexlocker 的析建構函式將被呼叫。其中將 mutex 解鎖,在 wait( ) 之前解鎖這很重要,否則將引起死鎖的可能性(第二線程一直等待 mutex 被解鎖,而主線程一直等待第二線程完成而操持 mutex 不放)。

qwaitcondition : : wakeone( ) 函式喚醒乙個正在等待某個條件的執行緒。被喚醒的執行緒取決於作業系統的排程策略,並不能控制和提前預知哪個執行緒將被喚醒。如果需要喚醒某個指定的執行緒,通常需要使用不同的等待條件,使用不同的執行緒專門等待不同的等待條件。

addtransaction( ) 函式將乙個 transaction 新增到佇列中,並喚醒 transaction 執行緒。所有訪問 transactions 的成員變數都由乙個 mutex 保護,因為在第二線程遍歷佇列中的 transaction 時主線程可能修改這些變數。

run函式中定義了不同的執行方法,獲取transaction的id,然後進行不同的侗族,也就是發射出不同的訊號。

然後在主線程中,connect這些訊號到主線程的槽函式中:

manager = p;

loginpage = null;

waitpage = null;

main = null;

msgbox = new messagebox(this);

tr_queue = new transactionthread();

connect(tr_queue, signal(loginsuccess()), this, slot(showmainframe()));

沒寫完,uicontrol就是個主介面,通過tr_queue中的不同訊號,來呼叫不同的槽函式。

Qt多執行緒基礎(三)子執行緒與主線程通訊

一 澄清概念 1.qt主線程 2.qt子執行緒 qt的子執行緒用於一些耗時操作,因此又被稱為工作執行緒。子執行緒不能用於直接重新整理介面 qwidget不可重入,qobject可重入 若子執行緒企圖修改介面控制項,可通過執行緒間通訊的方式 qt的訊號槽機制是跨執行緒的,因此可以用作執行緒間通訊。二 ...

QT子執行緒與主線程的訊號槽通訊

最近用qt做乙個伺服器,眾所周知,qt的主線程必須保持暢通,才能重新整理ui。所以,網路通訊端採用新開執行緒的方式。在涉及到使用子執行緒更新ui上的控制項時遇到了點兒麻煩。網上提供了很多同一執行緒不同類間採用訊號槽通訊的方式,但是並不完全適合執行緒間的訊號槽通訊,這主要體現在自定義訊息的傳遞上。首先...

QT中實現Thread於GUI主線程通訊的方法

目前只會一種,採用訊號槽機制。通常情況下,訊號和槽機制可以同步操作,這就意味著在發射訊號的時候,使用直接函式即可以立刻呼叫連線到乙個訊號上的多個槽。然而,當連線位於不同執行緒中的物件時,這一機制就會變得不同步起來,可以通過修改qobject connect 的第5個可選引數而改變。connect的第...