Reputation: 51917
When you dispose a “raw” .net timer, you can pass in a wait handle to be called once the Win32 timer has been destroyed and you can them assume that your call back will not be called. (And the timer will be considered "dead" by the GC)
How do I do this with a System.Timers.Timer?
Upvotes: 10
Views: 7433
Reputation: 65436
As System.Timers.Timer and System.Windows.Forms.Timer both use the ThreadPool it doesn't have a handle to an operating system timer, so there is no native timer resource that's disposed of - just a completed thread. I'm not sure you can capture a thread being recycled by the ThreadPool but I might be wrong.
You could maybe roll your own (I haven't tested this, and taking a ManualResetEvent in Dispose might be more useful):
void Run()
{
ManualResetEvent resetEvent = new ManualResetEvent(false);
System.Threading.Timer timer = new System.Threading.Timer(delegate { Console.WriteLine("Tick"); });
timer.Dispose(resetEvent);
MyTimer t = new MyTimer();
t.Interval = 1000;
t.Elapsed += delegate { t.Dispose(resetEvent); };
resetEvent.WaitOne();
}
public class MyTimer : System.Timers.Timer
{
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
public virtual void Dispose(WaitHandle handle)
{
handle.SafeWaitHandle.Close();
Dispose();
}
}
Upvotes: 0
Reputation: 38444
Set a flag before you call dispose, and check this flag in your elapsed handler. Even if the timer does fire, the flag will prevent any associated handler code from being run. You could formalize this pattern by writing a wrapper for the timer.
Make sure your flag is marked as volatile as it will be accessed from different threads.
Upvotes: 3