久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Qt——線程與定時(shí)器

 bling小興星 2020-03-23

一、定時(shí)器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類定義一個(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)行一次等,。

二、在多線程中使用QTimer

1.錯(cuò)誤用法

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

子類化QThread,,在線程類中定義一個(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)前線程id:") << QThread::currentThread();
}

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

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

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

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

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

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

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

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

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

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

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

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

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

2.正確用法一

在TestThread線程啟動(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)門estThread對(duì)象是在主線程中創(chuàng)建的,,它的QObject子對(duì)象也必須在主線程中創(chuàng)建,。所以不能指定父對(duì)象為TestThread。

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

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

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

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

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

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

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

3.正確用法二

無(wú)需子類化線程類,,通過信號(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);
}

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

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

Qt::AutoConnection:默認(rèn)值,。如果接收者處于發(fā)出信號(hào)的線程中,,則使用Qt::DirectConnection,,否則使用Qt::QueuedConnection,,連接類型由發(fā)出的信號(hào)決定。

Qt::DirectConnection:信號(hào)發(fā)出后立即調(diào)用槽函數(shù),,槽函數(shù)在發(fā)出信號(hào)的線程中執(zhí)行,。

Qt::QueuedConnection:當(dāng)控制權(quán)返還給接收者信號(hào)的事件循環(huán)中時(shí),開始調(diào)用槽函數(shù),。槽函數(shù)在接收者的線程中執(zhí)行,。

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

詳見原文

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多