Qt 執行緒與定時器

2021-08-26 14:44:56 字數 3279 閱讀 7595

我寫的簡單測試**:

the qtimer class provides repetitive and single-shot timers.

上面這段話摘自qt助手文件,我們使用qtimer類定義乙個定時器,它可以不停重複,也可以只進行一次便停止。

使用起來也很簡單:

qtimer *timer =newqtimer(this);

connect(timer, signal(timeout()),this, slot(update()));

timer->start(1000);

建立乙個qtimer物件,將訊號timeout()與相應的槽函式相連,然後呼叫start()函式。接下來,每隔一段時間,定時器便會發出一次timeout()訊號。

您可能會這麼做:

testthread::testthread(qobject *parent)

: qthread(parent)

voidtestthread::run()

voidtestthread::timeoutslot()

接下來在主線程中建立該執行緒物件,並呼叫它的start()方法:

m_pthread =newtestthread(this);

m_pthread->start();

看似十分自然,沒有什麼不妥,然而,編譯器將通知下面的錯誤資訊:

qobject::starttimer: timers cannot be started from another thread 

——定時器不能被其它執行緒start。

我們來分析一下:

剛開始只有主線程乙個,testthread的例項是在主線程中建立的,定時器在testthread的建構函式中,所以也是在主線程中建立的。

當呼叫testthread的start()方法時,這時有兩個執行緒。定時器的start()方法是在另乙個執行緒中,也就是testthread中呼叫的。

建立和呼叫並不是在同一執行緒中,所以出現了錯誤。

具體的原理可參考官方文件——點我

每個qobject例項都有乙個叫做「執行緒關係」(thread affinity)的屬性,或者說,它處於某個執行緒中。

預設情況下,qobject處於建立它的執行緒中。

當qobject接收佇列訊號(queued signal)或者傳來的事件(posted event),槽函式或事件處理器將在物件所處的執行緒中執行。

根據以上的原理,qt使用計時器的執行緒關係(thread affinity)來決定由哪個執行緒發出timeout()訊號。正因如此,你必須在它所處的執行緒中start或stop該定時器,在其它執行緒中啟動定時器是不可能的。

在testthread執行緒啟動後建立定時器。

voidtestthread::run()

有些地方需要注意:

1.不能像下面這樣給定時器指定父物件

m_ptimer =newqtimer(this);

否則會出現以下警告:

qobject: cannot create childrenfora parent that is in a differentthread.

(parent is testthread(0x709d88), parent'sthreadis qthread(0x6e8be8), currentthreadis testthread(0x709d88)

因為testthread物件是在主線程中建立的,它的qobject子物件也必須在主線程中建立。所以不能指定父物件為testthread。

2.必須要加上事件迴圈exec()

否則執行緒會立即結束,並發出finished()訊號。

另外還有一點需要注意,與start一樣,定時器的stop也必須在testthread執行緒中,否則會出錯。

voidtestthread::timeoutslot()

上面的**將出現以下錯誤:

qobject::killtimer: timers cannot be stopped from another thread

綜上,子類化執行緒類的方法可行,但是不太好。 

無需子類化執行緒類,通過訊號啟動定時器。

testclass::testclass(qwidget *parent)

: qwidget(parent)

通過movetothread()方法改變定時器所處的執行緒,不要給定時器設定父類,否則該函式將不會生效。

在訊號槽連線時,我們增加了乙個引數——連線型別,先看看該引數可以有哪些值:

qt::autoconnection:預設值。如果接收者處於發出訊號的執行緒中,則使用qt::directconnection,否則使用qt::queuedconnection,連線型別由發出的訊號決定。

qt::directconnection:訊號發出後立即呼叫槽函式,槽函式在發出訊號的執行緒中執行。

qt::queuedconnection:當控制權返還給接收者訊號的事件迴圈中時,開始呼叫槽函式。槽函式在接收者的執行緒中執行。

回到我們的例子,首先將定時器所處的執行緒改為新建的執行緒,然後連線訊號槽,槽函式在定時器所處的執行緒中執行

Qt子執行緒呼叫定時器

qt作為人機互動介面開發的主流工具,在工業控制領域也得到了廣泛的應用。工業控制中,需要對大量的實時資料讀取 顯示 計算和儲存,在乙個執行緒中實現這些功能,很有可能會造成介面卡死的情況。本文介紹一種不需要重寫子執行緒類的簡單方法,希望能給讀者一些啟發。初學qt,還在摸索中,所說內容難免有錯誤和不準確的...

執行緒定時器

定時器 timer類 schedule timertask物件,時間 定時排程 時間一到,他會執行timertask物件裡面的run方法。例項 10秒後該run方法執行 public class traditionaltimertest 1 0000 這個時間也可以設定成乙個具體時間,比如幾月幾號幾...

Qt之定時器

qt中定時器的使用有兩種方法,一種是使用qobject類提供的定時器,還有一種就是使用qtimer類。定時器類qtimer提供當定時器觸發的時候發射乙個訊號的定時器,它提供只觸發一次的超時事件。1 啟動定時器 int m timerid starttimer 300 啟動乙個qtimer型別的定時器...