I'm trying to implement Undo function in my app. I have code like this Timer timer = new Timer(UndoDeleteTimerFinish, email, UndoBannerDisappearTime, Timeout.Infinite);
and UndoDeleteTimerFinish()
will make the banner disppear. However, sometimes the banner will stuck on the screen and I found that in this kind of scenario, UndoDeleteTimerFinish()
won't be called. I think the timer must be GC collected. I'm wondering how to prevent timer get GC collected and at the same time be responsive and allow user to interact with the app.

- 1,762
- 1
- 20
- 36
-
is that a System.Threading.Timer ? Also where is UndoDeleteTimerFinish callback, the location of that callback may keep the Timer from being garbage collected. That is, if the object with that callback is eligible for GC and the only references the Timer haave are to that object, then the Timer is eligible for GC. – brakeroo Oct 31 '16 at 16:43
-
1Infamous problem with that timer, you have to keep a reference on the object yourself. An "undo delete" timer surely will work just as well with a DispatcherTimer. Well, better in more than one way. – Hans Passant Oct 31 '16 at 17:00
-
Does this answer your question? [Can Timers get automatically garbage collected?](https://stackoverflow.com/questions/18136735/can-timers-get-automatically-garbage-collected) – Michael Freidgeim Nov 20 '20 at 12:33
1 Answers
The timer has a reference to the object that defines UndoDeleteTimerFinish. If that object's only refrence is to the Timer and vice-versa they will both be eligible for garbage collection.
Quick and dirty fix is to have an object that is not garbage collected hold a reference to your Timer.
class ObjectNotGettingGarbageCollected{
Timer _timer; //won't be GC'd
SomeMethod(){
_timer = new Timer(UndoDeleteTimerFinish, email, UndoBannerDisappearTime, Timeout.Infinite)
}
}
Also as long as the state object (email in you case) is referenced somewhere, the CLR keeps the timer in its timer queue and the timer object won't get garbage collected. So I would check what is the status of the 'email' object which you pass as the state parameter to your Timer.
More about this here:
The System.Threading.Timer constructor has several overloads; all except one take a state parameter which is passed to the TimerCallback delegate when the timer fires.
It turns out that this state parameter (and the TimerCallback delegate) have an interesting effect on garbage collection: if neither of them reference the System.Threading.Timer object, it may be garbage collected, causing it to stop. This is because both the TimerCallback delegate and the state parameter are wrapped into a GCHandle. If neither of them reference the timer object, it may be eligible for GC, freeing the GCHandle from its finalizer.
The single-parameter constructor does not suffer from this problem, because it passes this for the state (not null). Most real-world usage of System.Threading.Timer either references the timer from the callback or uses the timer for the state, so this interesting garbage collection behavior will probably not be noticed.
http://blog.stephencleary.com/2011/07/systemthreadingtimer-constructor-and.html