I'm new to c# programming so bear with me, there is a concept I couldn't understand in the event handling pattern, here a simple implementation to an event handling
class test
{
someobject.Click += OnClick;
private void OnClick(object sender,EventArgs e)
{
SomeClass someclass = new SomeClass();
}
}
the problem is why the variable someclass doesn't get garbage collected since it's a local variable in the method OnClick and gets out of scope when this method finishes
It does get released, just not right away. Garbage collection occurs when
The system has low physical memory. This is detected by either the low memory notification from the OS or low memory as indicated by the host.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
This means that you can't be certain when SomeClass is getting freed unless you call for the collection yourself.
Source: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
Related
I'm starting to learn about GC and finalization, and I've come across quite a simple example where the behaviour of the application is quite unexpected to me.
(Note: I'm aware that finalizers should be used only be used with unmanaged resources and using the disposable pattern, I just want to understand what is going on here.)
This is a simple console app that generates a "saw-tooth" pattern of memory. The memory rises to around 90MB and then does a GC, drops and begins to rise again, never going beyond 90MB.
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100000; i++)
{
MemoryWaster mw = new MemoryWaster(i);
Thread.Sleep(250);
}
}
}
public class MemoryWaster
{
long l = 0;
long[] array = new long[1000000];
public MemoryWaster(long l)
{
this.l = l;
}
//~MemoryWaster()
//{
// Console.WriteLine("Finalizer called.");
//}
}
If I remove the comment with the finalizer, the behaviour is very different - the application does one or two GCs at the start but then the memory increases in a linear way until it is using over 1GB of memory (at which point I terminate the application)
From what I have read, this is because instead of releasing the item, the GC moves the object to the finalization queue. The GC starts a thread to execute the finalizer methods, and then waits for another GC to remove the finalized objects. This can be an issue when the finalizer methods are very long-running but this isn't the case here.
If I manually trigger run GC.Collect() every few iterations, the app behaves as expected and I see the saw-tooth pattern of the memory getting released.
My question is - why does the large amount of memory being used by the application not trigger a GC automatically? In the example with finalizers included, would the GC ever run again after the first time?
Do not rely on Finalizers. They are a safety net that you should never get to, not the first option. If the finalizers have to clean up after you, you already messed up terribly.
I have two basic rules regarding disposeables, that always worked:
Never split up the creation and disposing of a instance. Create, use, dispose. All in teh same piece of code, ideally using a using block.
If you can not do the 1st thing - like when you are wrapping around something that Implements IDisposeable - your class implements IDisposeable for the sole purpose of relaying the Dispose call.
As for the GC:
While the GC runs, all other Threads have to be paused. This is a absolute rule. As a result the GC is quite lazy. It tries to avoid running. Indeed if it only runs once during application close, that is the ideal case.
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.
public struct LocalTLS : IDisposable
{
public byte[] bArr;
public string str;
public LocalTLS(int k)
{
str = "Labamba";
bArr = new byte[20000];
}
public void Dispose()
{
MessageBox.Show("In Dispose");
//Thread.FreeNamedDataSlot("jaja");
int k = 90;
k += 90;
}
}
private void buttonTLS_retreive_Click(object sender, EventArgs e)
{
LocalTLS lts = new LocalTLS(1);
}
After the click event returns I expect the Dispose call but THAT NEVER HAPPENS, Can Some one explain. I do not want to do any manual steps like calling Dispose or do using. I want that to happen automatically.
Well thanks for all your answers, I wanted to implement a a class for LocalDataStoreSlot, that will automatically free the Slot and it goes out of scope, as shown in the commented code. This will free the developer from remembering to
call dispose, wherein the actual FreeNamedDataSlot(...) happens. Seems like that is not possible
The CLR does not perform garbage collection all the time, otherwise your program will be very slow because it is performing GC. To perform GC, the CLR has to suspend ALL the threads before reclaiming memory used by out of scope objects. That is a very big performance impact.
The CLR will perform GC and call the object's Dispose method when necessary. Do not call the object's Dispose() method unless you have a good reason. If the object is associated to native system handles, network connections, file handles etc., those are good reasons to use the using keyword or call it's Dispose() method. Generally the CLR will GC objects that are out of scope fast enough such that your application will not run out of memory.
I understand your concern, you believe that byte[20000] is a significant memory footprint to your application and you want to control your memory usage carefully. But this is not C++. The CLR will automatically manage memory for you. In my past 7 years of .NET develop I have only come across one application where the default GC is not fast enough and I have to call Dispose() on objects manually. So in short, just hand over memory management to the CLR - it does a very good job.
p.s. if you're interested in how GC works internally, there are a number of in-depth articles online. Just search - you'll find them.
You've to wrap your object declaration inside using like this:
using(LocalTLS lts = new LocalTLS(1))
{
// use lts here
} // at this point, the Dispose method is called.
or call Dispose method manually:
lts.Dispose();
Also, the Dispose() method is automatically called when there is no reference to lts in the code, by the Garbage Collector.
Its a struct, it lives on the memory stack not the memory heap. So its not going to be collected by the garage collector like objects do, so the GC will not call the dispose method. Your struct "LocalTLS " will be freed up and taken off the memory stack when your method ends. When it does this, it does not look for the IDisposable interface.
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