2014-09-10 25 views
0

我已經在資源(類)實例上實現了一個空閒計時器,該實例可以同時在多個應用程序中打開。因此,idleTimer不僅是一個簡單的QTimer,但是插槽(觸發器)需要驗證在過去的N分鐘內沒有其他應用程序訪問過相同的資源。如果是這種情況,則重置計時器(不更新lastAccessedTime值),否則資源關閉。計時器因此是一個單一的計時器,並且lastAccessTime保存在QSharedMemory對象中。singleshot在OS X上的QTimer多次或過早快速啓動

下面是一些跟蹤輸出:

### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83601 timer QTimer(0x11d273d60) triggered 1 times 
### slotIdleTimedOut ->handleIdleTiming: setting QTimer(0x11d273d60) for wallet "kdewallet" handle 0 timeout to 6 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ;  elapsed minutes= 5.83634 timer QTimer(0x11d273d60) triggered 2 times 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer QTimer(0x11d273d60) triggered 3 times 
### "Google Contacts()of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer QTimer(0x11d273d60) triggered 4 times 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83634 timer QTimer(0x11d273d60) triggered 5 times 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83635 timer QTimer(0x11d273d60) triggered 6 times 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ;  elapsed minutes= 5.83635 timer QTimer(0x11d273d60) triggered 7 times 
### "Google Contacts() of type Google Contacts" Idle timeout 6 min. for KWallet::Wallet(0x105d1f900) "kdewallet" handle 0 ; elapsed minutes= 5.83635 timer QTimer(0x11d273d60) triggered 8 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle 0 ; elapsed minutes= 6 timer QTimer(0x120a1b5f0) triggered 1 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00008 timer QObject(0x0) triggered 2 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00009 timer QObject(0x0) triggered 3 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer QObject(0x0) triggered 4 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer QObject(0x0) triggered 5 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer QObject(0x0) triggered 6 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer QObject(0x0) triggered 7 times 
### "KMail" Idle timeout 6 min. for KWallet::Wallet(0x1083f1ac0) "kdewallet" handle -1 ; elapsed minutes= 6.00012 timer QObject(0x0) triggered 8 times 

原則的作品,但我注意到兩兩件事:

  • 定時器早期的火一點。當然這會導致計時器被重置。
  • 它快速連續發射數次。事實上,早期的火災應該重置它並沒有絲毫的影響。

下面是我的代碼的相關部分,包括在每次資源訪問時重置計時器的函數以及計時器的觸發槽。

任何想法,我做錯了嗎?在重新設置單拍模式並重新啓動之前,我停止計時器。對象和應用程序標識符顯示它確實是多次觸發的同一個計時器,並且即使在刪除計時器對象後也可以觸發它。

難道觸發器插槽不是應用程序(或甚至是實例)特定的,不知何故導致1個實例接收來自設置此計時器實例的各種應用程序的所有其他實例的idleTimer觸發信號? idleTimer僅在類析構函數中設置爲NULL,並且/或者當timeOut爲< = 0時,所以我不能阻止我的觸發器槽可以使用NULL計時器對象進行調用!

從計時器安裝功能(handleIdleTimingKWallet::Wallet成員因爲是idleTimer本身):

// This function is to be called at every operation that is supposed to launch or reset 
// the idle timing. @p timeOut is a time in minutes. 
void handleIdleTiming(const char *caller="", bool touchAccessTime=true) 
{ 
    // ... 
    if(timeOut >= 0){ 
     if(!idleTimer){ 
      idleTimer = new QTimer(0); 
     } 
     else{ 
      idleTimer->stop(); 
     } 
     // when the idle timer fires, the wallet is supposed to be closed. There is thus 
     // no reason to use a repeating timer. 
     idleTimer->setSingleShot(true); 
     connect(idleTimer, SIGNAL(timeout()), q, SLOT(slotIdleTimedOut())); 
     if(touchAccessTime){ 
      if(lastAccessTime.lock()){ 
       *((double*)lastAccessTime.data()) = HRTime_Time(); 
       lastAccessTime.unlock(); 
      } 
      else{ 
       qDebug() << "Cannot lock lastAccessTime for wallet" << name << "error" << lastAccessTime.errorString(); 
      } 
     } 
     idleTimer->start(timeOut * 60 * 1000); 

定時器觸發插槽:

void Wallet::slotIdleTimedOut() 
{ double lastAccessTime = 0; 
    // check the last time anyone accessed this wallet: 
    if(d->lastAccessTime.lock()){ 
     lastAccessTime = *((double*)d->lastAccessTime.data()); 
     d->lastAccessTime.unlock(); 
    } 
    else{ 
     qDebug() << "Cannot lock lastAccessTime for wallet" << d->name << "error" << d->lastAccessTime.errorString(); 
    } 
    // the time elapsed since that last access, in minutes: 
    double elapsed = (HRTime_Time() - lastAccessTime)/60; 
    d->idleTimerTriggered += 1; 
    qDebug() << "###" << appid() << "Idle timeout" << d->timeOut << "min. for" << this << d->name << "handle" << d->handle 
     << "; elapsed minutes=" << elapsed << "timer" << d->idleTimer << "triggered" << d->idleTimerTriggered << "times"; 
    if(elapsed >= d->timeOut){ 
     // we have a true timeout, i.e. we didn't access the wallet in timeOut minutes, and no one else did either. 
     slotWalletClosed(d->handle); 
    } 
    else{ 
     // false alarm, reset the timer, but there's no need to count this as an access! 
     d->handleIdleTiming(__FUNCTION__, false); 
    } 
} 
+0

難道這是因爲我在'new QTimer(0)'之後重複調用connect()(可能)而不是一次? – RJVB 2014-09-10 15:25:10

回答

0

肯定是曾經因爲我發了連接語句每次我重置計時器,而不是隻創建一次後。