最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt實現線程與定時器的方法

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

一、定時器QTimer類

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.

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

使用起來也很簡單:

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

創(chuàng)建一個QTimer對象,將信號timeout()與相應的槽函數相連,然后調用start()函數。接下來,每隔一段時間,定時器便會發(fā)出一次timeout()信號。

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

二、在多線程中使用QTimer

1.錯誤用法

您可能會這么做:

子類化QThread,在線程類中定義一個定時器,然后在run()方法中調用定時器的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("當前線程id:") << QThread::currentThread();
}

接下來在主線程中創(chuàng)建該線程對象,并調用它的start()方法:

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

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

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

——定時器不能被其它線程start。

我們來分析一下:

剛開始只有主線程一個,TestThread的實例是在主線程中創(chuàng)建的,定時器在TestThread的構造函數中,所以也是在主線程中創(chuàng)建的。

當調用TestThread的start()方法時,這時有兩個線程。定時器的start()方法是在另一個線程中,也就是TestThread中調用的。

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

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

每個QObject實例都有一個叫做“線程關系”(thread affinity)的屬性,或者說,它處于某個線程中。

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

當QObject接收隊列信號(queued signal)或者傳來的事件(posted event),槽函數或事件處理器將在對象所處的線程中執(zhí)行。

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

2.正確用法一

在TestThread線程啟動后創(chuàng)建定時器。

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.不能像下面這樣給定時器指定父對象

m_pTimer = new QTimer(this);

否則會出現以下警告:

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) 

因為TestThread對象是在主線程中創(chuàng)建的,它的QObject子對象也必須在主線程中創(chuàng)建。所以不能指定父對象為TestThread。

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

否則線程會立即結束,并發(fā)出finished()信號。

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

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

上面的代碼將出現以下錯誤:

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

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

3.正確用法二

無需子類化線程類,通過信號啟動定時器。

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);
}

通過moveToThread()方法改變定時器所處的線程,不要給定時器設置父類,否則該函數將不會生效。

在信號槽連接時,我們增加了一個參數——連接類型,先看看該參數可以有哪些值:

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

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

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

相關文章

  • 利用Matlab實現迭代適應點算法

    利用Matlab實現迭代適應點算法

    道格拉斯-普克算法(Douglas–Peucker?algorithm,亦稱為拉默-道格拉斯-普克算法、迭代適應點算法、分裂與合并算法)是將曲線近似表示為一系列點,并減少點的數量的一種算法。本文將利用Matlab實現這一算法,需要的可以參考一下
    2022-04-04
  • c++ 單線程實現同時監(jiān)聽多個端口

    c++ 單線程實現同時監(jiān)聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監(jiān)聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下
    2021-03-03
  • C++ throw關鍵字實現拋出異常和異常規(guī)范

    C++ throw關鍵字實現拋出異常和異常規(guī)范

    本文主要介紹了C++ throw關鍵字實現,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++實現LeetCode(49.群組錯位詞)

    C++實現LeetCode(49.群組錯位詞)

    這篇文章主要介紹了C++實現LeetCode(49.群組錯位詞),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • C語言實現學生成績管理系統(tǒng)

    C語言實現學生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現學生成績管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C++指針學習詳解

    C++指針學習詳解

    指針在 C\C++ 語言中是很重要的內容,并且和指針有關的內容一向令初學者頭大,這篇文章主要給大家介紹了關于C/C++中指針的相關資料,需要的朋友可以參考下
    2021-09-09
  • vs2017智能感知錯誤解決代碼標紅但編譯通過問題

    vs2017智能感知錯誤解決代碼標紅但編譯通過問題

    這篇文章主要介紹了vs2017智能感知錯誤代碼標紅但編譯通過問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • C語言數組入門之數組的聲明與二維數組的模擬

    C語言數組入門之數組的聲明與二維數組的模擬

    這篇文章主要介紹了C語言數組入門之數組的聲明與二維數組的模擬,數組學習的同時也要相應理解C語言指針的作用,需要的朋友可以參考下
    2015-12-12
  • C++示例講解vector容器

    C++示例講解vector容器

    這篇文章主要介紹了C++?容器?Vector?的使用方法,Vector?是一個能夠存放任意類型的動態(tài)數組,有點類似數組,是一個連續(xù)地址空間,下文更多詳細內容的介紹,需要的小伙伴可以參考一下
    2022-07-07
  • 深入了解C語言中常見的文件操作方法

    深入了解C語言中常見的文件操作方法

    這篇文章主要為大家詳細介紹了C語言中常見的文件操作,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06

最新評論

鄂托克旗| 新乐市| 库尔勒市| 昌吉市| 吉木乃县| 石门县| 乌鲁木齐县| 大埔县| 崇州市| 沙湾县| 怀集县| 黄骅市| 东宁县| 蕉岭县| 依安县| 曲水县| 上饶市| 仁布县| 邢台县| 三原县| 杂多县| 邻水| 寿宁县| 四平市| 合山市| 建宁县| 永宁县| 平湖市| 临漳县| 会理县| 富川| 黑龙江省| 白朗县| 察哈| 农安县| 唐河县| 内丘县| 文成县| 阜新| 白河县| 怀柔区|