Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does GC.SuppressFinalize keep an object rooted

In the reference source for Task.Delay() in .NET, I came across a snippet of code:

// ... and create our timer and make sure that it stays rooted.
if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
{
    promise.Timer = new Timer(state => ((DelayPromise)state).Complete(), promise, millisecondsDelay, Timeout.Infinite);
    promise.Timer.KeepRootedWhileScheduled();
}

The method KeepRootedWhileScheduled is implemented thusly:

GC.SuppressFinalize(m_timer);

What is the purpose of calling GC.SuppressFinalize? Does it really root the object for the garbage collector, is the comment incorrect, or is there something else that I'm misunderstanding?

like image 457
zastrowm Avatar asked Sep 03 '25 07:09

zastrowm


1 Answers

Keeping a System.Threading.Timer rooted is certainly very important, it stops ticking when you don't. But no, this method has a very misleading name. It probably did something very different in an early version, then it was discovered later that whatever hokey-pokey it did wasn't necessary. It shouldn't, the task keeps a reference on it. This is conjecture without having access to that early source code of course.

What remains is a micro-optimization, nothing unusual in .NET Framework code. Presumably the timer always gets disposed, no matter what happens, so there's no need for its finalizer. Sounds about right, you'd have to think of a scenario where the task suffers an exception while it is executing Delay(). Well, that doesn't happen. Fairly sloppy editing btw, that's not common in framework code.

like image 142
Hans Passant Avatar answered Sep 04 '25 21:09

Hans Passant