欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Qt實(shí)現(xiàn)線(xiàn)程與定時(shí)器的方法

 更新時(shí)間:2022年01月14日 10:11:13   作者:去冰三分糖  
本文主要介紹了Qt實(shí)現(xiàn)線(xiàn)程與定時(shí)器的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一、定時(shí)器QTimer類(lèi)

The QTimer class provides repetitive and single-shot timers.

The QTimer class provides a high-level programming interface for timers. To use it, create a QTimer, connect its timeout() signal to the appropriate slots, and call start(). From then on, it will emit the timeout() signal at constant intervals.

上面這段話(huà)摘自Qt助手文檔,我們使用QTimer類(lèi)定義一個(gè)定時(shí)器,它可以不停重復(fù),也可以只進(jìn)行一次便停止。

使用起來(lái)也很簡(jiǎn)單:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);

創(chuàng)建一個(gè)QTimer對(duì)象,將信號(hào)timeout()與相應(yīng)的槽函數(shù)相連,然后調(diào)用start()函數(shù)。接下來(lái),每隔一段時(shí)間,定時(shí)器便會(huì)發(fā)出一次timeout()信號(hào)。

更多用法這里就不講了,您可以自行參考官方文檔。比如如何停止、如何令定時(shí)器只運(yùn)行一次等。

二、在多線(xiàn)程中使用QTimer

1.錯(cuò)誤用法

您可能會(huì)這么做:

子類(lèi)化QThread,在線(xiàn)程類(lèi)中定義一個(gè)定時(shí)器,然后在run()方法中調(diào)用定時(shí)器的start()方法。

TestThread::TestThread(QObject *parent)
    : QThread(parent)
{
    m_pTimer = new QTimer(this);
    connect(m_pTimer, &QTimer::timeout, this, &TestThread::timeoutSlot);
}
 
void TestThread::run()
{
    m_pTimer->start(1000);
}
 
void TestThread::timeoutSlot()
{
    qDebug() << QString::fromLocal8Bit("當(dāng)前線(xiàn)程id:") << QThread::currentThread();
}

接下來(lái)在主線(xiàn)程中創(chuàng)建該線(xiàn)程對(duì)象,并調(diào)用它的start()方法:

m_pThread = new TestThread(this);
m_pThread->start();

看似十分自然,沒(méi)有什么不妥,然而,編譯器將通知下面的錯(cuò)誤信息:

 QObject::startTimer: Timers cannot be started from another thread 

——定時(shí)器不能被其它線(xiàn)程start。

我們來(lái)分析一下:

剛開(kāi)始只有主線(xiàn)程一個(gè),TestThread的實(shí)例是在主線(xiàn)程中創(chuàng)建的,定時(shí)器在TestThread的構(gòu)造函數(shù)中,所以也是在主線(xiàn)程中創(chuàng)建的。

當(dāng)調(diào)用TestThread的start()方法時(shí),這時(shí)有兩個(gè)線(xiàn)程。定時(shí)器的start()方法是在另一個(gè)線(xiàn)程中,也就是TestThread中調(diào)用的。

創(chuàng)建和調(diào)用并不是在同一線(xiàn)程中,所以出現(xiàn)了錯(cuò)誤。

具體的原理可參考官方文檔——點(diǎn)我

每個(gè)QObject實(shí)例都有一個(gè)叫做“線(xiàn)程關(guān)系”(thread affinity)的屬性,或者說(shuō),它處于某個(gè)線(xiàn)程中。

默認(rèn)情況下,QObject處于創(chuàng)建它的線(xiàn)程中。

當(dāng)QObject接收隊(duì)列信號(hào)(queued signal)或者傳來(lái)的事件(posted event),槽函數(shù)或事件處理器將在對(duì)象所處的線(xiàn)程中執(zhí)行。

根據(jù)以上的原理,Qt使用計(jì)時(shí)器的線(xiàn)程關(guān)系(thread affinity)來(lái)決定由哪個(gè)線(xiàn)程發(fā)出timeout()信號(hào)。正因如此,你必須在它所處的線(xiàn)程中start或stop該定時(shí)器,在其它線(xiàn)程中啟動(dòng)定時(shí)器是不可能的。

2.正確用法一

在TestThread線(xiàn)程啟動(dòng)后創(chuàng)建定時(shí)器。

void TestThread::run()
{
    m_pTimer = new QTimer();
    m_pTimer->setInterval(1000);
    connect(m_pTimer, &QTimer::timeout, this, &TestThread::timeoutSlot);
    m_pTimer->start();
    this->exec();
}

有些地方需要注意:

1.不能像下面這樣給定時(shí)器指定父對(duì)象

m_pTimer = new QTimer(this);

否則會(huì)出現(xiàn)以下警告:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is TestThread(0x709d88), parent's thread is QThread(0x6e8be8), current thread is TestThread(0x709d88) 

因?yàn)門(mén)estThread對(duì)象是在主線(xiàn)程中創(chuàng)建的,它的QObject子對(duì)象也必須在主線(xiàn)程中創(chuàng)建。所以不能指定父對(duì)象為T(mén)estThread。

2.必須要加上事件循環(huán)exec()

否則線(xiàn)程會(huì)立即結(jié)束,并發(fā)出finished()信號(hào)。

另外還有一點(diǎn)需要注意,與start一樣,定時(shí)器的stop也必須在TestThread線(xiàn)程中,否則會(huì)出錯(cuò)。

void TestThread::timeoutSlot()
{
    m_pTimer->stop();
    qDebug() << QString::fromLocal8Bit("當(dāng)前線(xiàn)程id:") << QThread::currentThread();
}

上面的代碼將出現(xiàn)以下錯(cuò)誤:

QObject::killTimer: Timers cannot be stopped from another thread

綜上,子類(lèi)化線(xiàn)程類(lèi)的方法可行,但是不太好。 

3.正確用法二

無(wú)需子類(lèi)化線(xiàn)程類(lèi),通過(guò)信號(hào)啟動(dòng)定時(shí)器。

TestClass::TestClass(QWidget *parent)
    : QWidget(parent)
{
    m_pThread = new QThread(this);
    m_pTimer = new QTimer();
    m_pTimer->moveToThread(m_pThread);
    m_pTimer->setInterval(1000);
    connect(m_pThread, SIGNAL(started()), m_pTimer, SLOT(start()));
    connect(m_pTimer, &QTimer::timeout, this, &ThreadTest::timeOutSlot, Qt::DirectConnection);
}

通過(guò)moveToThread()方法改變定時(shí)器所處的線(xiàn)程,不要給定時(shí)器設(shè)置父類(lèi),否則該函數(shù)將不會(huì)生效。

在信號(hào)槽連接時(shí),我們?cè)黾恿艘粋€(gè)參數(shù)——連接類(lèi)型,先看看該參數(shù)可以有哪些值:

  • Qt::AutoConnection:默認(rèn)值。如果接收者處于發(fā)出信號(hào)的線(xiàn)程中,則使用Qt::DirectConnection,否則使用Qt::QueuedConnection,連接類(lèi)型由發(fā)出的信號(hào)決定。
  • Qt::DirectConnection:信號(hào)發(fā)出后立即調(diào)用槽函數(shù),槽函數(shù)在發(fā)出信號(hào)的線(xiàn)程中執(zhí)行。
  • Qt::QueuedConnection:當(dāng)控制權(quán)返還給接收者信號(hào)的事件循環(huán)中時(shí),開(kāi)始調(diào)用槽函數(shù)。槽函數(shù)在接收者的線(xiàn)程中執(zhí)行。

回到我們的例子,首先將定時(shí)器所處的線(xiàn)程改為新建的線(xiàn)程,然后連接信號(hào)槽,槽函數(shù)在定時(shí)器所處的線(xiàn)程中執(zhí)行。

到此這篇關(guān)于Qt實(shí)現(xiàn)線(xiàn)程與定時(shí)器的方法的文章就介紹到這了,更多相關(guān)Qt 線(xiàn)程與定時(shí)器 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于C/C++中的side effect(負(fù)效應(yīng))和sequence point(序列點(diǎn))

    關(guān)于C/C++中的side effect(負(fù)效應(yīng))和sequence point(序列點(diǎn))

    不知你在寫(xiě)code時(shí)是否遇到這樣的問(wèn)題?int i = 3; int x = (++i) + (++i) + (++i); 問(wèn)x值為多少?進(jìn)行各種理論分析,并在編譯器上實(shí)踐,然而可能發(fā)現(xiàn)最終的結(jié)果是不正確的,也是不穩(wěn)定的,不同的編譯器可能會(huì)產(chǎn)生不同的結(jié)果。這讓人很頭疼
    2013-10-10
  • C語(yǔ)言實(shí)現(xiàn)十六進(jìn)制與二進(jìn)制的相互轉(zhuǎn)換

    C語(yǔ)言實(shí)現(xiàn)十六進(jìn)制與二進(jìn)制的相互轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了如何利用c語(yǔ)言實(shí)現(xiàn)將文件中十六進(jìn)制數(shù)據(jù)與二進(jìn)制數(shù)據(jù)相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以學(xué)習(xí)一下
    2022-11-11
  • 基于堆的基本操作的介紹

    基于堆的基本操作的介紹

    本篇文章對(duì)堆的基本操作進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • 適合新手小白DEV?C++的使用方法

    適合新手小白DEV?C++的使用方法

    Dev-C++是一個(gè)Windows環(huán)境下C/C++的集成開(kāi)發(fā)環(huán)境(IDE),它是一款自由軟件,遵守GPL,下面這篇文章主要給大家介紹了關(guān)于適合新手小白DEV?C++的使用方法,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • C++實(shí)現(xiàn)通訊錄系統(tǒng)項(xiàng)目實(shí)戰(zhàn)

    C++實(shí)現(xiàn)通訊錄系統(tǒng)項(xiàng)目實(shí)戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)通訊錄系統(tǒng)項(xiàng)目實(shí)戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++之CNoTrackObject類(lèi)和new delete操作符的重載實(shí)例

    C++之CNoTrackObject類(lèi)和new delete操作符的重載實(shí)例

    這篇文章主要介紹了C++之CNoTrackObject類(lèi)和new delete操作符的重載實(shí)例,是C++程序設(shè)計(jì)中比較重要的概念,需要的朋友可以參考下
    2014-10-10
  • c語(yǔ)言中字符串與字符串?dāng)?shù)組詳解

    c語(yǔ)言中字符串與字符串?dāng)?shù)組詳解

    在C語(yǔ)言當(dāng)中,字符串?dāng)?shù)組可以使用char a[] [10]; 或者char *a[]; 表示,下面這篇文章主要給大家介紹了關(guān)于c語(yǔ)言中字符串與字符串?dāng)?shù)組的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • QT網(wǎng)絡(luò)通信TCP客戶(hù)端實(shí)現(xiàn)詳解

    QT網(wǎng)絡(luò)通信TCP客戶(hù)端實(shí)現(xiàn)詳解

    這篇文章主要為大家詳細(xì)介紹了QT網(wǎng)絡(luò)通信TCP客戶(hù)端實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • c++中nlohmann?json的基本使用教程

    c++中nlohmann?json的基本使用教程

    nlohmann/json 是一個(gè)C++實(shí)現(xiàn)的JSON解析器,使用非常方便直觀,下面這篇文章主要給大家介紹了關(guān)于c++中nlohmann?json基本使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • C語(yǔ)言代碼實(shí)現(xiàn)三子棋游戲

    C語(yǔ)言代碼實(shí)現(xiàn)三子棋游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言代碼實(shí)現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11

最新評(píng)論