singleshot在OS X上的QTimer多次或过早快速启动
问题描述:
我已经在资源(类)实例上实现了一个空闲计时器,该实例可以同时在多个应用程序中打开。因此,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计时器对象进行调用!
从计时器安装功能(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);
}
}
答
肯定是曾经因为我发了连接语句每次我重置计时器,而不是只创建一次后。
难道这是因为我在'new QTimer(0)'之后重复调用connect()(可能)而不是一次? – RJVB 2014-09-10 15:25:10