关于 QTimer 的具体实现,翻看源码源于一次面试经历。被问到 QTimer 的问题,我随口说了一句:Windows 平台下是用 Windows API 实现的,然后便引起了怀疑,不过我据理力争,便也作罢。所以回来之后,就又确认了一下。
要找这个佐证就必然要从
start()
方法顺藤摸瓜。
void QTimer::start()
if (id != INV_TIMER) // stop running timer
stop();
nulltimer = (!inter && single);
id = QObject::startTimer(inter, Qt::TimerType(type));
}
事实证明还是走到了
QObject
中。继续顺藤摸瓜。
int QObject::startTimer(int interval, Qt::TimerType timerType)
Q_D(QObject);
if (Q_UNLIKELY(interval < 0)) {
qWarning("QObject::startTimer: Timers cannot have negative intervals");
return 0;
if (Q_UNLIKELY(!d->threadData->hasEventDispatcher())) {
qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
return 0;
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QObject::startTimer: Timers cannot be started from another thread");
return 0;
int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
d->extraData->runningTimers.append(timerId);
return timerId;
}
void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
Q_ASSERT(internalHwnd);
Q_Q(QEventDispatcherWin32);
bool ok = false;
calculateNextTimeout(t, qt_msectime());
uint interval = t->interval;
if (interval == 0u) {
// optimization for single-shot-zero-timer
QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
ok = true;
} else if (interval < 20u || t->timerType == Qt::PreciseTimer) {
// 3/2016: Although MSDN states timeSetEvent() is deprecated, the function
// is still deemed to be the most reliable precision timer.
t->fastTimerId = timeSetEvent(interval, 1, qt_fast_timer_proc, DWORD_PTR(t),
TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
ok = t->fastTimerId;
if (!ok) {
// user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
ok = SetTimer(internalHwnd, t->timerId, interval, 0);
if (!ok)
qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
}
熟悉的 Windows API 就被发现了。如果当初我能记得
QObject
里边的调用细节,或许应该就在面试的让对方少些疑问了。