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(),不管什麼情況,都能保證這種先後關係。