Can a Timer destroy itself?

  • Thread starter Thread starter Peter Oliphant
  • Start date Start date
P

Peter Oliphant

I'd like to be able to destroy a Timer in it's own event handler. That is,
within it's tick handler I'd like to delete the Timer itself (e.g., for
one-shot timers). Is this possible?

In general, can a class instance destroy itself via one of it's own methods?
 
Peter said:
In general, can a class instance destroy itself via one of it's own methods?

Firing an event is like calling a method or function. So the event
handler is called from the object itself, which is still alive at that
time, and therefore it is potentially dangerous to delete it. It's OK to
delete if you are sure that the method where the event is fired from no
longer refers to any of the member variables (or internal resources).

But wait a minute, is it possible at all in .NET to delete an instance?
There is no such thing as a destructor in CLI. You can't force the
deletion of allocated objects, and the garbage collector will only
delete the object once it's not reference by anywhere else. As long as
the object is still alive, it's not going to be garbage collected.

When you Dispose an object, you only destroy its underlying handle. For
example, if it's a file object, Dipose will close the file. If it's a
Graphics object, the device context is released. But the object itself
is still alive after calling Dispose, as far as its member variables go.
Its underlying resource or unmanaged implementation is dead, though,
after a Dispose. In the new C++/CLI syntax you no longer call Dispose,
but use the delete operator instead. The delete operator performs just a
call to Dipose, if I understand it correctly. It's still the garbage
collector that removes the object from the memory.

Whether it's safe to call "delete timer1" from timer1's event handler, I
can't tell for sure, but it might be. It depends how safe its internal
implementation is.

Here's an example where it's not safe to call delete from an event handler:

ref class Unsafe
{
public:
Unsafe()
: unmanaged(new Unmanaged)
{
}
~Unsafe()
{
delete unmanaged;
}
delegate void NotifyEvent(Unsafe^ sender);
event NotifyEvent OnNotify;
void FireNotify()
{
OnNotify(this);
unmanaged->DoSomething(); // booooom!!!!!!
}
private:
Unmanaged* unmanaged;
};

If you call "delete sender" from OnNotify's handler, FireNotify will
crash, because parts of the class's internal implementation is already
dead, and the class doesn't even have protection built in against that.

Also note that an event can have multiple handlers. If you do have
multiple handlers, it can't be guaranteed that a specific handler is the
last one to be called. If you dispose the sender from the handler, other
handlers may still want to access the object. Once again, it's sometimes
possible to make such a class that's safe to be disposed from a handler,
but generally speaking such safety can not always be guaranteed. Without
knowing the implementation, you can never be sure, in my opinion.

Tom
 
Peter said:
I'd like to be able to destroy a Timer in it's own event handler. That is,
within it's tick handler I'd like to delete the Timer itself (e.g., for
one-shot timers). Is this possible?

How about disabling it?
timer1->Enabled = false;

Or if you want delayed destruction, ::PostMessage, I'm not sure its
WinForms equivalent.

Tom
 
I was thinking about the ability to create Timers on the fly in such a way
that if my program goes to the same code the old timers will be gone (think
of it as trying not to have 'timer leak' much like a 'memory leak'). If the
Timers go out of scope this should do exactly that, so that is how I'll do
it.

I don't NEED this functionality really, I was just trying to give a timer
class I'm creating (more of a rapper on the existing Timer class) as much
functionality as possible. But no need to do this if it's too dangerous! :)

Thanks for the detailed response!!! :)
 
Peter said:
I was thinking about the ability to create Timers on the fly in such a way
that if my program goes to the same code the old timers will be gone (think
of it as trying not to have 'timer leak' much like a 'memory leak').

I wouldn't worry about that. A timer that is not enabled does not exist.
I'm not sure about the WinForms timer, but in Delphi when you disable a
timer, the framework automatically calls KillTimer. So the underlying
timer resource simply does not exist when the timer is not enabled. What
exists is a few bytes of memory (required by the timer wrapper object)
on the heap, that's it. This also means that you could pre-create a
timer for every situation, without having to worry about exceeding the
maximum system timer count. I have no reason to believe the WinForms
implementation consumes a timer reasource when a timer is disabled. It
would be a bad implementation in my opinion.

Tom
 
Back
Top