如何讓 Qt 的程序使用 Sleep

Qt 爲何沒有提供 Sleep

論壇上不時見到有人問:

  1. Qt 爲什麼沒有提供跨平臺的 sleep 函數?

  2. 使用平臺相關的 Sleep 或 nanosleep 以後,界面爲什麼沒有反應?

  3. QThread 中提供了protected 權限的 sleep 函數,如何用到主線程中?

  4. 使用 QTest 中的 qSleep,在windows下如何隱藏控制檯?

這些問題其實歸結爲一點:在主線程中使用這些函數是一種錯誤,這會直接導致界面無法刷新,用戶與程序無法交互。

Qt不提供,是因爲你不需要在主線程中使用 sleep 函數。

如何讓程序等待一段時間

QTime

 

QTime t;
t.start();
while(t.elapsed()<1000);

這種死循環也是一種常見錯誤用法。但改成正確的還是比較簡單的:

 

QTime t;
t.start();
while(t.elapsed()<1000)
    QCoreApplication::processEvents();

不停地處理事件,以使得程序保持響應。

QElapsedTimer

這是Qt4.7引入的新的類,和QTime相比,它提供了更快的計算 elapsed 時間的方法。

QElapsedTimer t;
t.start();
while(t.elapsed()<1000)
    QCoreApplication::processEvents();

QTest::qWait

這是QTest模塊提供的等待函數

下面是其源代碼(和我們前面的代碼很像吧?):

namespace QTest
{
    inline static void qWait(int ms)
    {
        Q_ASSERT(QCoreApplication::instance());

        QElapsedTimer timer;
        timer.start();
        do {
            QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
            QTest::qSleep(10);
        } while (timer.elapsed() < ms);
    }
...

其實沒什麼魔力,對吧?但是因爲它QTest模塊,所以在程序中我們不要使用它。

QEventLoop

配合QTimer使用局部的 eventLoop 也是一個不錯的選擇。例子:

    QEventLoop eventloop;
    QTimer::singleShot(100, &eventloop, SLOT(quit()));
    eventloop.exec();

QTimer 和 QBasicTimer

這兩個和本文沒有什麼直接關係,QTimer估計大家都很熟了。而QBasicTimer估計很少有人用。

  • 與QTimer相比,QBasicTimer更快速、輕量、底層。

  • 與QTimer相比,它不是QObject的派生類。

跨平臺的sleep

儘管一開始我們就說了,不需要這個東西。但不排除某種場合下,你確實需要這個東西。如何實現一個跨平臺的 sleep 呢?

我們一開始也提到了,QThread類 和 QTest模塊都提供了sleep函數,其實我們只需要看看他們的源碼就夠了:

QTest 模塊中的函數很簡單(windows下調用Sleep,其他平臺調用 nanosleep):

void QTest::qSleep(int ms)
{
    QTEST_ASSERT(ms > 0);

#ifdef Q_OS_WIN
    Sleep(uint(ms));
#else
    struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
    nanosleep(&ts, NULL);
#endif
}

看QThread的源碼,windows下同樣直接調用Sleep,但非windows的實現比這個就複雜多了:

 


[cpp] view plaincopy

  1. /*  /internal 

  2.     helper function to do thread sleeps, since usleep()/nanosleep() 

  3.     aren't reliable enough (in terms of behavior and availability) 

  4. */  

  5. static void thread_sleep(struct timespec *ti)  

  6. {  

  7.     pthread_mutex_t mtx;  

  8.     pthread_cond_t cnd;  

  9.     pthread_mutex_init(&mtx, 0);  

  10.     pthread_cond_init(&cnd, 0);  

  11.     pthread_mutex_lock(&mtx);  

  12.     (void) pthread_cond_timedwait(&cnd, &mtx, ti);  

  13.     pthread_mutex_unlock(&mtx);  

  14.     pthread_cond_destroy(&cnd);  

  15.     pthread_mutex_destroy(&mtx);  

  16. }  

  17. void QThread::sleep(unsigned long secs)  

  18. {  

  19.     struct timeval tv;  

  20.     gettimeofday(&tv, 0);  

  21.     struct timespec ti;  

  22.     ti.tv_sec = tv.tv_sec + secs;  

  23.     ti.tv_nsec = (tv.tv_usec * 1000);  

  24.     thread_sleep(&ti);  

  25. }  



轉載自:http://blog.csdn.net/dbzhang800/article/details/6300425


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