我在游戏中使用了一个计时器,它在一个单例内启动并且每个毫秒都有一个回调。但是,有时它的运行速度是原来的两倍。这真的很少见,我只看过2到3次(10.000+版本,数千次执行)。
这是代码的重要部分:
//local variable in the .cpp:
static float milliseconds=0;
//the "actual" variable used in the game
long int MilliSecondTimer::milliseconds=0;
void CALLBACK TimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
milliseconds++;
MilliSecondTimer::GetInstance()->SetTime(int(milliseconds), int(guimseconds));
}
MilliSecondTimer::MilliSecondTimer()
{
UINT TimerID = timeSetEvent(1, 0, TimerProc, 0, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
}
如果单例的创建时间超过1毫秒,那么它将被调用两次,因为定时器函数将调用
MilliSecondTimer::GetInstance()->SetTime(...)
谢谢!
答案 0 :(得分:1)
这很难再现,因为你说它很少发生。但我相信你最初的想法,因为问题的原因可能是真的。在timeSetEvent的MSDN文档中,它说:
多媒体计时器以自己的线程运行
这意味着,正如你所说的,如果单例创建时间超过1毫秒,那么在这种情况下,单例的构造函数将被调用两次。对构造函数的第二次调用可能来自第一个定时器回调函数中的MilliSecondTimer::GetInstance()->SetTime(...)
调用,因为此时尚未创建单例,MilliSecondTimer::GetInstance()
将再次调用构造函数,这又会创建另一个计时器对象。由于每个计时器都在自己的线程中运行,现在你将有两个计时器(递增)相同的数据(静态浮点毫秒),这解释了为什么它运行速度快两倍。如果是这种情况,那么由于在进程中创建了单例的两个实例,但是单例实例指针最终指向其中一个,因此可能还会发生内存泄漏。