Я реализовал таймер простоя на ресурсе (классе), экземпляры которого могут быть открыты сразу в нескольких приложениях. Следовательно, idleTimer
- это не только простой QTimer
, но слот (триггер) должен проверить, не обращались ли другие приложения к тем же ресурсам в течение последних N минут. Если это так, таймер сбрасывается (без обновления значения lastAccessedTime
), иначе ресурс будет закрыт. Таким образом, таймер является однократным, а lastAccessTime
хранится в объекте QSharedMemory.singleclhot QTimer на OS X быстрых огней несколько раз и слишком рано
Вот некоторые Трассировочная:
### "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
Принцип работы, но я заметил 2 вещи:
- таймер срабатывает рановато. Конечно, это приводит к сбросу таймера.
- это пожары несколько раз в быстрой последовательности. Тот факт, что ранний огонь должен сбросить его, не имеет ни малейшего эффекта.
Ниже приведена соответствующая часть моего кода, включая функцию, которая сбрасывает таймер при каждом доступе к ресурсу и слот триггера таймера.
Любая идея, что я делаю неправильно? Я останавливаю таймер перед тем, как (re) установит его в режим singleleshot и начнет его (заново). Идентификаторы объектов и приложений показывают, что это действительно тот же самый таймер, который срабатывает несколько раз и что он может срабатывать даже после того, как я удалил объект таймера.
Возможно, слот триггера не является специфичным для приложения (или даже экземпляра), что приводит к тому, что один экземпляр получает триггерные сигналы idleTimer
из всех других экземпляров в различных приложениях, которые устанавливают экземпляр этого таймера? idleTimer
получает значение NULL только в деструкторе класса и/или когда timeOut
равно < = 0, поэтому я зашел в тупик, что мой слот триггера может быть вызван с помощью объекта NULL timer!
С таймером установки функции (handleIdleTiming
, член KWallet::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);
}
}
Может ли это быть потому, что я вызываю connect() (потенциально) несколько раз, а не один раз после 'new QTimer (0)'? – RJVB