Why I see "Hello" words many times when I add timer.Dispose() to my code in release mode. Without timer.Dispose() I see "Hello" once. Thanks.
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Method(object state)
{
Console.WriteLine(state);
GC.Collect();
}
static void Main()
{
var timer = new Timer(Method, "Hello", 0, 200);
Console.ReadLine();
timer.Dispose();
}
}
}
You see it once because the garbage collector has collected the timer object.
Since there are no more references to it that is considered "live" the garbage collector is free to do so.
In release mode, and when no debugger is attached, the JITter builds up knowledge of where local variables are used in a method. Once a variable is no longer used, it is no longer considered to be a root if the method is currently executing below that point. As such, the garbage collector can collect the timer object. However, before it can do so it must finalize the object, which destroys the underlying timer object and stops it from executing.
In debug builds, the scope of all local variables are artificially extended to be the entire method, so that if you place a breakpoint in the method you can inspect variables, even if the program would no longer actually require that variable to exist.
When you added the call to dispose, you extended the lifetime of the variable, and thus prevented the garbage collector from collecting your timer object.
Since you provoke a garbage collection in the timer event handler method, you effectively destroy the timer yourself in this case. When you extended the lifetime of the variable by adding in the call to Dispose, the garbage collector still runs as part of your timer event handler, but it cannot yet collect the timer, so it keeps running.
The answer left here by Hans Passant describes this much better than my meager attempt above:
Understanding Garbage Collection in .NET.
I suspect it's because GC.Collect will not collect the timer object when it's still referenced below the current line of code.
timer.Dispose(); is acting like GC.KeepAlive(timer); in this instance.
If you remove both the Dispose and the GC.Collect(), you will get a few "Hello"s, and then the GC will decide to collect by itself, and you'll get no more.
Related
While looking at the Timer documentation I ran across the following example with this comment:
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
code in between
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
Does this mean that the GC in C# is allowed to garbage collect local variables even if it would have side effects? Presumably because I'm not accessing the timer afterwards again the GC can collect it earlier?
Not sure I'm a fan of such an optimization if I understand this correctly (but then I probably don't ;) )
Yes, GC might collect local variable before ending of the scope, as soon as after last use of the variable. Putting GC.KeepAlive at the end of the method ensures that the variable will be 'alive' until the KeepAlive call.
C# is imperative language so the GC hasn't been designed to know anything about side effects.
As far as I understand the GC, it will mark any variable or object that it believes is no longer needed as a candidate for Garbage Collection during the next GC cycle. I'm not certain I understand the particular application here, but I do know there are cases where the GC might mark a resource for collection when it is still needed (but does not appear so due to the way the code is written).
Normally, during methods, an object or variable stays in scope for the duration of the method call, but if the method call lasts longer than the time between GC cycles, the GC might see your Timer object as out of scope and mark it for collection. Adding the GC.KeepAlive method forces the GC to wait until the method exits before acting on the Timer object.
I have a timer in C# which executes some code inside it's method. Inside the code I'm using several temporary objects.
If I have something like Foo o = new Foo(); inside the method, does that mean that each time the timer ticks, I'm creating a new object and a new reference to that object?
If I have string foo = null and then I just put something temporal in foo, is it the same as above?
Does the garbage collector ever delete the object and the reference or objects are continually created and stay in memory?
If I just declare Foo o; and not point it to any instance, isn't that disposed when the method ends?
If I want to ensure that everything is deleted, what is the best way of doing it:
with the using statement inside the method
by calling dispose method at the end
by putting Foo o; outside the timer's method and just make the assignment o = new Foo() inside, so then the pointer to the object is deleted after the method ends, the garbage collector will delete the object.
1.If I have something like Foo o = new Foo(); inside the method, does that
mean that each time the timer ticks,
I'm creating a new object and a new
reference to that object?
Yes.
2.If I have string foo = null and then I just put something temporal in foo,
is it the same as above?
If you are asking if the behavior is the same then yes.
3.Does the garbage collector ever delete the object and the reference or
objects are continually created and
stay in memory?
The memory used by those objects is most certainly collected after the references are deemed to be unused.
4.If I just declare Foo o; and not point it to any instance, isn't that
disposed when the method ends?
No, since no object was created then there is no object to collect (dispose is not the right word).
5.If I want to ensure that everything is deleted, what is the best way of
doing it
If the object's class implements IDisposable then you certainly want to greedily call Dispose as soon as possible. The using keyword makes this easier because it calls Dispose automatically in an exception-safe way.
Other than that there really is nothing else you need to do except to stop using the object. If the reference is a local variable then when it goes out of scope it will be eligible for collection.1 If it is a class level variable then you may need to assign null to it to make it eligible before the containing class is eligible.
1This is technically incorrect (or at least a little misleading). An object can be eligible for collection long before it goes out of scope. The CLR is optimized to collect memory when it detects that a reference is no longer used. In extreme cases the CLR can collect an object even while one of its methods is still executing!
Update:
Here is an example that demonstrates that the GC will collect objects even though they may still be in-scope. You have to compile a Release build and run this outside of the debugger.
static void Main(string[] args)
{
Console.WriteLine("Before allocation");
var bo = new BigObject();
Console.WriteLine("After allocation");
bo.SomeMethod();
Console.ReadLine();
// The object is technically in-scope here which means it must still be rooted.
}
private class BigObject
{
private byte[] LotsOfMemory = new byte[Int32.MaxValue / 4];
public BigObject()
{
Console.WriteLine("BigObject()");
}
~BigObject()
{
Console.WriteLine("~BigObject()");
}
public void SomeMethod()
{
Console.WriteLine("Begin SomeMethod");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("End SomeMethod");
}
}
On my machine the finalizer is run while SomeMethod is still executing!
The .NET garbage collector takes care of all this for you.
It is able to determine when objects are no longer referenced and will (eventually) free the memory that had been allocated to them.
Objects are eligable for garbage collection once they go out of scope become unreachable (thanks ben!). The memory won't be freed unless the garbage collector believes you are running out of memory.
For managed resources, the garbage collector will know when this is, and you don't need to do anything.
For unmanaged resources (such as connections to databases or opened files) the garbage collector has no way of knowing how much memory they are consuming, and that is why you need to free them manually (using dispose, or much better still the using block)
If objects are not being freed, either you have plenty of memory left and there is no need, or you are maintaining a reference to them in your application, and therefore the garbage collector will not free them (in case you actually use this reference you maintained)
Let's answer your questions one by one.
Yes, you make a new object whenever this statement is executed, however, it goes "out of scope" when you exit the method and it is eligible for garbage collection.
Well this would be the same as #1, except that you've used a string type. A string type is immutable and you get a new object every time you make an assignment.
Yes the garbage collector collects the out of scope objects, unless you assign the object to a variable with a large scope such as class variable.
Yes.
The using statement only applies to objects that implement the IDisposable interface. If that is the case, by all means using is best for objects within a method's scope. Don't put Foo o at a larger scope unless you have a good reason to do so. It is best to limit the scope of any variable to the smallest scope that makes sense.
Here's a quick overview:
Once references are gone, your object will likely be garbage collected.
You can only count on statistical collection that keeps your heap size normal provided all references to garbage are really gone. In other words, there is no guarantee a specific object will ever be garbage collected.
It follows that your finalizer will also never be guaranteed to be called. Avoid finalizers.
Two common sources of leaks:
Event handlers and delegates are references. If you subscribe to an event of an object, you are referencing to it. If you have a delegate to an object's method, you are referencing it.
Unmanaged resources, by definition, are not automatically collected. This is what the IDisposable pattern is for.
Finally, if you want a reference that does not prevent the object from getting collected, look into WeakReference.
One last thing: If you declare Foo foo; without assigning it you don't have to worry - nothing is leaked. If Foo is a reference type, nothing was created. If Foo is a value type, it is allocated on the stack and thus will automatically be cleaned up.
Yes
What do you mean by the same? It will be re-executed every time the method is run.
Yes, the .Net garbage collector uses an algorithm that starts with any global/in-scope variables, traverses them while following any reference it finds recursively, and deletes any object in memory deemed to be unreachable. see here for more detail on Garbage Collection
Yes, the memory from all variables declared in a method is released when the method exits as they are all unreachable. In addition, any variables that are declared but never used will be optimized out by the compiler, so in reality your Foo variable will never ever take up memory.
the using statement simply calls dispose on an IDisposable object when it exits, so this is equivalent to your second bullet point. Both will indicate that you are done with the object and tell the GC that you are ready to let go of it. Overwriting the only reference to the object will have a similar effect.
The garbage collector will come around and clean up anything that no longer has references to it. Unless you have unmanaged resources inside Foo, calling Dispose or using a using statement on it won't really help you much.
I'm fairly sure this applies, since it was still in C#. But, I took a game design course using XNA and we spent some time talking about the garbage collector for C#. Garbage collecting is expensive, since you have to check if you have any references to the object you want to collect. So, the GC tries to put this off as long as possible. So, as long as you weren't running out of physical memory when your program went to 700MB, it might just be the GC being lazy and not worrying about it yet.
But, if you just use Foo o outside the loop and create a o = new Foo() each time around, it should all work out fine.
As Brian points out the GC can collect anything that is unreachable including objects that are still in scope and even while instance methods of those objects are still executing. consider the following code:
class foo
{
static int liveFooInstances;
public foo()
{
Interlocked.Increment(ref foo.liveFooInstances);
}
public void TestMethod()
{
Console.WriteLine("entering method");
while (Interlocked.CompareExchange(ref foo.liveFooInstances, 1, 1) == 1)
{
Console.WriteLine("running GC.Collect");
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine("exiting method");
}
~foo()
{
Console.WriteLine("in ~foo");
Interlocked.Decrement(ref foo.liveFooInstances);
}
}
class Program
{
static void Main(string[] args)
{
foo aFoo = new foo();
aFoo.TestMethod();
//Console.WriteLine(aFoo.ToString()); // if this line is uncommented TestMethod will never return
}
}
if run with a debug build, with the debugger attached, or with the specified line uncommented TestMethod will never return. But running without a debugger attached TestMethod will return.
I have a piece of code like this:
Class Program
{
static StreamReader sr = null;
static int var=0;
static Program()
{
sr = new StreamReader("input.txt")
}
~Program()
{
sr.Dispose();
}
static void main(string args[])
{
//do something with input here
}
}
This may not be a good practice, but I just want to use this example to ask how the deconstructor and GC works.
My question is: Will ~Program() get called at a non-determined time or it won't be called at all in this case. If the deconstructor won't get called, then how GC collect the unmanaged resources and managed resources.
It probably wouldn't reclaim those resources until the AppDomain or process is unloaded.
If you never instantiate an object, it will never be destroyed. This is exactly why you want, probably something like a Singleton. I believe there is a flavor called "Phoenix Singleton," that will allow a Singleton to be cleaned up and then rebuilt when it is needed again. You could implement it using a WeakReference to the singleton object.
In any case, for a simple program that runs for a bounded period of time, I wouldn't worry about it unless it becomes a problem... the resources will be cleaned up when the process exits.
Your case is quite unclear, as the finalizer would not be called without creating an instance of the class.
However, only calling dispose does nothing towards garbage collection of the object itself, it merely tells the object to release any resource (especially handles etc.). So if you want the GC to collect the instance, you need to set the reference to null, and if there is no other live reference to the instance it will eventually be collected.
Basically each static reference can be seen as root reference, which is included in the GC checks for live references. All instances which cannot be reached through a live reference (directly or indirectly) are candidates for collection. It does not matter if the reference "variable" was static or not.
There is no such thing as a static finalizer (destructor) in C#. Therefore, unless an instance of Program is ever actually created, ~Program() will never be called.
When (if) it is called, it only calls the Dispose() method of the StreamReader; because a reference to the StreamReader is still retained after the finalizer is called, the instance will never be garbage collected until the program exits.
A static reference will root an instance until it is explicitly set to null or its assembly is unloaded. If neither of these happens the instance a static reference points to will remain in use and thus will not be collected. If it isn't eligible for garbage collection its finalizer will not be called either.
Btw GC only handles managed memory. It doesn't handled unmanaged resources. For that you need IDiposable and/or finalizers.
I ran the following code and found that finalizer is always called. But many articles said that finalizer is non-desterministic.
class Test
{
Test()
{
throw new Exception();
}
~Test()
{
Console.WriteLine("Finalizer is called");
}
static void Main()
{
try
{
new Test();
}
catch { }
}
It is still non-deterministic in your case. Non-deterministic means the amount of time it takes for something to happen cannot be pre-calculated. Note that being unable to correctly determine when something will happen does not necessarily mean random-time but in most cases they are roughly the same.
People who never have to control car brakes, industrial robots or the space shuttle generally should not care weather a piece of code is deterministic or not.
note: I have written code to control industrial robots so I sometimes need to care about my code being executed at the exact moment I want it to be.
The garbage collector calls the finalizer when it collects the object. You can suppress the finalizer call by calling GC.SuppressFinalize(); Documentation
You could place this call inside Dispose() to stop the garbage collector from collecting the class after its resources have been disposed.
In your case, the finalizer is running as part of application shutdown. From the docs:
During shutdown of an application
domain, Finalize is automatically
called on objects that are not exempt
from finalization, even those that are
still accessible.
Non-deterministic refers to when Finalize will be called. But except in exceptional cases (like power being cut off or the process being abruptly killed), the finalizer will eventually be called.
There are cases when it may not be called; and cases where even if it is called, it may not be allowed to complete.
While there are certain occasions when the finalizer will not be called, it will typically be called. The big issue is when it is called, hence it is non-deterministic.
C# is garbage-collected and the garbage collector runs at unspecified intervals. Therefore, if the finalizer needs to do something time-sensitive, it is best to use Dispose instead of a finalizer. For example, you might want to close a database connection immediately instead of leaving it open while waiting for the garbage collector.
That code is so simple that the .NET Runtime can run the finalizer with out problems but in high load applications the Finalizers are only called when garbage collection runs.
There is here an extract of this article
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
Finalization
The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory.
Here is an oversimplification of what happens: when the garbage collector detects that an object is garbage, the garbage collector calls the object's Finalize method (if it exists) and then the object's memory is reclaimed. For example, let's say you have the following type (in C#):
public class BaseObj {
BaseObj() {}
protected override void Finalize() {
// Perform resource cleanup code here...
// Example: Close file/Close network connection
Console.WriteLine("In Finalize.");
}
}
Now you can create an instance of this object by calling:
BaseObj bo = new BaseObj();
Some time in the future, the garbage collector will determine that this object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing "In Finalize" to appear in the console window and reclaiming the memory block used by this object.
I have the following code (cut down for readability):
Main Class:
public StartProcess()
{
Thinker th = new Thinker();
th.DoneThinking += new Thinker.ProcessingFinished(ThinkerFinished);
th.StartThinking();
}
void ThinkerFinished()
{
Console.WriteLine("Thinker finished");
}
Thinker Class:
public class Thinker
{
private System.Timers.Timer t;
public delegate void ProcessingFinished();
public event ProcessingFinished DoneThinking;
BackgroundWorker backgroundThread;
public Thinker() { }
public StartThinking()
{
t = new System.Timers.Timer(5000); // 5 second timer
t.AutoReset = false;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
// start a background thread to do the thinking
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork += new DoWorkEventHandler(BgThread_DoWork);
backgroundThread.RunWorkerAsync();
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DoneThinking();
}
BgThread_DoWork(object sender, DoWorkEventArgs e)
{
// work in here should go for much less than 5 seconds
// it will die if it doesn't
t.Stop();
DoneThinking();
}
}
What I originally expected to happen was that the event handler in the main class would prevent the Thinker from being garbage collected.
Apparently this isn't the case.
I'm now wondering whether garbage collection will occur regardless of whether this thread is "busy" or not. In other words, is there a chance it will be garbage collected before the 5 second timeout has expired?
To put it another way, is it possible for the garbage collector to collect my Thinker before it's finished processing?
No, a thread is considered live as long as it is referenced, and any thread that is running is considered to be referenced (IIRC a running thread registers its stack as a GC root, and that stack will reference the thread).
That said i'm looking at your example and i don't understand where you believe a thread is being spawned?
No, a running thread's stack acts as a root for GC purposes. That stack will live as long as the Thread is running, so the Thread itself won't be collected as long its running.
Here's an article that mentions (among other things) what the roots are for GC purposes. To save some time, GC roots are global objects, static objects, all reference on all thread stacks, and all CPU registers containing references.
Your question is a little difficult to answer. Like Joel, as far as I can tell, you have nothing on the stack referencing your timer, which itself is the only thing referencing the thread. Given that, one would expect the Thinker instance would be collected.
I was curious about this, and needed a more concrete explanation of what might happen, so I dug into Reflector a bit. As it turns out, System.Timers.Timer ultimately creates a System.Threading.Timer, which internally creates an instance of TimerBase, an internal class. TimerBase derives from CriticalFinalizerObject, which is a system type that ensures that all code in a Constrained Execution Region (CER) will execute before the implementing class is fully finalized and discarded by the GC. TimerBase is also IDisposable, and its dispose method loops and spinwaits until a lock is released. At this point, I started running into external code, so I am not exactly sure how the lock is initialized or released.
However, based on how the TimerBase class is written, the fact that it derives from CriticalFinalizerObject, and the fact that its dispose spinwaits until a lock is released, I think its safe to say that a thread that is not referenced by anything will not be finalized until that code is done executing. That said...it is important to note that it quite likely will be processed by the GC...quite possibly more than once, as finalization can greatly lengthen the process of collection on finalized objects. For those that are CriticalFinalizerObjects, the finalization process could take even longer if there is actively executing code that the CER is ensuring will fully execute.
That could mean you have exactly the opposite problem if your Thinkers take a while to execute. Rather than those objects being collected prematurely, they will go into a lengthy finalization, and anything they reference ending up in gen2, and living for quite some time until the GC is finally able to fully collect them.
If I'm reading this right (and I could be way off here), it can be collected because it's not currently doing anything.
If you had local variables in your start method, and that method was still active, those variables would still be "in scope" on the stack and provide a root for your thread. But the only variable you use is your private timer, and since that is rooted with the thread itself and the thread has nothing on the stack, there's nothing left to keep it alive.
I agree and disagree, If the reference to the thread object is lost the thread will be terminated and garbage collected. In your case it might not be as such because it is not directly using threads and is using timer. But if you had called a method in a thread and the thread reference was lost with the end of the method then it would be collected by GC