【发布时间】:2009-01-24 23:18:21
【问题描述】:
我在我的应用程序中使用计时器队列,并将指向我自己的 C++ Timer 对象之一的指针作为“参数”传递给回调(在 CreateTimerQueueTimer 中)。然后我在回调中调用对象的虚方法。
Timer 对象的析构函数将确保使用 DeleteTimerQueueTimer() 取消计时器。
static void callback( PVOID param, BOOLEAN timerOrWaitFired )
{
Timer* timer = reinterpret_cast< Timer* >( param );
timer->TimedOut();
}
class Timer
{
public:
Timer();
virtual ~Timer()
{
::DeleteTimerQueueTimer( handle );
}
void Start( double period )
{
::CreateTimerQueueTimer( &handle, ..., &callback, this, ... );
}
virtual void TimedOut() = 0;
...
};
但是,有一个微妙的竞争条件,如果回调已经被调用,但计时器对象在调用 TimedOut() 之前 被销毁,应用程序崩溃,因为回调调用虚拟不存在的对象上的方法。或者更糟糕的是,它正在被删除。
我确实有互斥锁来控制多线程调用,但我仍然遇到问题。
使用对象指针作为回调参数真的是个好主意吗?由于无法保证线程之间的同步,这对我来说只是闻起来很糟糕。
有没有更好的解决方案?其他人是做什么的?
发生的一件事是保留一组指向每个 Timer 实例的指针(在构造函数中添加,在析构函数中删除)。但我认为这行不通,因为如果 Timer 派生自,我们只会从基类析构函数的集合中删除指针;如果我们已经开始销毁派生对象,则损坏已经造成。
干杯。
【问题讨论】: