QT中 延時處理的幾種方法

QTimer

[static] void QTimer::singleShot(int msec, const QObject *receiver, const char *member)

#include <QApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTimer::singleShot(600000, &app, SLOT(quit()));
    ...
    return app.exec();
}

QDateTime.secsTo

QDateTime start = QDateTime::currentDateTime();
QDateTime now;
do{
    now = QDateTime::currentDateTime();
} while (start.secsTo(now) <= 5);  //5爲需要延時的秒數

QWaitCondition

QWaitCondition 用於多線程的同步,一個線程調用QWaitCondition::wait() 阻塞等待,直到另一個線程調用QWaitCondition::wake() 喚醒才繼續往下執行。

在處理生產者和消費者線程關係時,建議使用QWaitCondition作爲QSemaphore的替代方法,來控制共享或者同步數據。

先看一個不太嚴謹的例子:

// 生產者線程
sendData(&data);//發送數據給消費者線程
mutex.lock();
condition.wait(&mutex); 
if (m_bReceived)
{
	handlePacket();//處理消費者線程傳回的包
}
mutex.unlock();

// 消費者線程
m_bReceived = recvData(buffer);//解析生產者發送過來的數據
condition.wakeAll();

在該例中,主線程(生產者)sendData(&data)給消費者線程發送數據,假設消費者線程收到數據後立馬回包(這種情況是可能發生的,因爲線程的調度是無序的,所以無法保證主線程總會被優先調度)。此時主線程還未來得及調用 condition.wait(&mutex),消費者線程已經調用了condition.wakeAll(),很顯然,這次喚醒是無效的,但主線程繼續調用 wait(),然後一直阻塞在那裏。

嚴謹的代碼應該是這樣的:

// 生產者線程
mutex.lock();
sendData(&data);//發送數據給消費者線程	
condition.wait(&mutex); 
if (m_bReceived)
{
	handlePacket();//處理消費者線程傳回的包
}
mutex.unlock();

// 消費者線程
m_bReceived = recvData(buffer);//解析生產者發送過來的數據
mutex.lock();
condition.wakeAll();
mutex.unlock();

主線程中,在發送數據之前先執行mutex.lock(),即使消費者線程收到數據後,也不會立即執行condition.wakeAll()。而是在調用 mutex.lock() 時阻塞住(因爲主線程已經把mutex佔據上鎖了,再嘗試上鎖就會被阻塞),直到主線程 condition.wait(&mutex)真正執行操作系統的阻塞等待指令並釋放mutex,消費者線程的 mutex.lock() 才能出阻塞,繼續往下執行,調用 wakeAll(),此時一定能成功喚醒主線程。

小結:通過 mutex 把有嚴格時序要求的代碼保護起來,同時把 wakeAll() 也用同一個 mutex 保護起來,這樣能保證:一定先有 wait() ,再有 wakeAll(),不管什麼情況,都能保證這種先後關係。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章