I am dealing with some legacy code that probably predates .NET 2. The library itself is custom asynchronous TCP communication layer used by our server.
There is a class there inheriting from System.Net.Sockets.TcpClient and the whole class hierarchy around it that implements dispose pattern and finalizers (the latter likely not needed).
My question is about suspicious line of code found in the method that handle TCP client disconnected event:
// Hack to ensure that client has disconnected
GC.Collect();
which is executed after calling methods disposing of our communication class hierarchy that eventually calls System.Net.Sockets.TcpClient Dispose method.
On a 64-bit server that can serve many clients and use gigabytes of RAM these calls can be quite expensive. I could not find anything about forcing garbage collection upon TCP client disconnection?
Two things will happen after you force GC with GC.Collect().
Memory used by unreachable objects that don't have finalizers will be reclaimed.
Objects that implement finalizers will be placed on finalizer queue, and the finalizers will be executed soon.
The comment suggests that GC.Collect() is not called to reclaim memory, but rather to execute finalizers to dispose unmanaged resources.
If IDisposable is used correctly, there is no need to rely on finalizers. Probably there are some IDisposable objects that are not Disposed correctly. You'll have to find them. One way to do it is to examine what finalizers are executed. Some memory profilers can also track such objects (for example .NET memory profiler's Dispose Tracker).
Are the c# ManualResetEvent and AutoResetEvent classes expensive to create or to maintain?
Do they consume some kind of limited Windows kernel resources, and if so, how limited is it?
E.g. if I have code that can create a new AutoResetEvent every 100ms (to be disposed shortly afterwards), should I worry about putting old AutoResetEvents in a pool and reusing them, or is that not a significant concern?
Since they are IDisposables, I presume they consume some sort of limited resource. Just how much do they consume, and at which point should I start worrying about using too many of them?
The fact that there is a ManualResetEventSlim, but no AutoResetEventSlim also worries me a bit.
ManualResetEvent uses Wait Handles whereas ManualResetEventSlim uses Busy Spinning
The best performance, in order, is: 1) standard locking (Monitor) 2) "slim" event classes 3) standard event classes
Given your use case, I would recommend using the "slim" classes, since you will only be waiting for a short amount of time. Also, if a "slim" class waits for too long, it behaves as a "non-slim" class anyway.
Note you cannot use the "slim" classes across processes.
EDIT: This is why AutoResetEvent does not have a "slim" version - basically it's because the wait times of AutoResetEvent are typically longer than ManualResetEvent, so it isn't appropriate to use "busy spinning"
EDIT: A wait handle inherits from MarshalByRefObject. Ultimately .NET runtime sets up a proxy (TransparentProxy class) for remote access to your wait handle.
See here and here for more information.
The objects of type FileStream or DB handles have to be properly closed as it use Windows handles internally. Likewise, Threads also use Windows handles right? Does thread has some internal mechanisms to release those Windows handles?
Thread does not implement IDisposable so it can't be disposed unlike Stream or DB related objects.
Runtime takes care of necessary cleanup of related native object when thread's code finishes execution and GC will normally take care of managed Thread object similarly to other finalizable objects.
Note that there is no direct consistent relationship between OS and managed threads Getting the thread ID from a thread.
Edit: My question isn't getting the main answer that I was looking for. I wasn't clear. I would really like to know two things:
Can NOT calling Dispose() cause memory leaks?
What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?
I was under the impression that memory leaks could occur if Dispose() isn't called on IDisposable objects.
Per the discussion on this thread, my perception was incorrect; a memory leak will NOT occur if Dispose() isn't called.
Why ever bother calling Dispose() then? Is it just to free the resource immediately, instead of sometime later? What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?
Dispose is used to release non-managed resources. This could mean memory, if a class allocated non-managed memory, but it is more often native objects and resources like open files and database connections.
You often need to call Dispose on a class that itself doesn't have any non-managed resources, but it does contain another class that is disposable and may have non-managed resources.
It's also sometimes useful for developers to implement dispose to ensure deterministic finalization--guaranteeing the order in which resources are freed.
Also note that classes that implement dispose often also have a finalizer to release resourcdes if Dispose is not called. Objects with a finalizer have a different life-cycle than classes without one. When they are ready for GC, the GC will see that they have a finalizer and instead of immediately collecting the object when the GC is ready to, it puts it into the finalization queue. This means that the object lives for one extra GC iteration. When you call dispose, the implementation usually (but is not required to) calls GC.SuppressFinalize() which means the finalizer no longer needs to be called.
If a class implements IDisposable, you should always call Dispose().
While some other answers seem to be suggesting that you can get away with not calling it, this is really bad advice. You should always call Dispose on any IDisposable resource.
Some .NET objects have what's called a "finalizer" - something you can define on your own classes as well, but that you rarely see done in a typical C# programmer's code. The finalizer is what runs when the garbage collector destroys the object, and sometimes it will call Dispose - but only if the implementer of the class made it that way.
The best practice is to always Dispose - no matter what. There are plenty of libraries I've used where not calling Dispose on a resource results in a memory leak, a connection leak, a operating system resource leak, or other kinds of horribleness. And the garbage collector will not reconcile the problem, because they don't implement any custom finalizer.
See related: Will the Garbage Collector call IDisposable.Dispose for me?
The convention is that if an object implements IDisposable you should call Dispose() or use the "using" pattern. The difference between Dispose() and waiting for the destructor (finalizer) to execute is that Dispose() is called right away and can be used for freeing some important resources like db connections, files, devices, unmanaged oejects, etc.
So to summarize - if it is IDisposable - Dispose() it!
Not calling Dispose will not ever (*see note 2 on wrong implementation) cause traditional "memory leak" (memory is never freed till end of the process).
The "only" thing that will happen in relation to memory is it will be freed in non-deterministic moment in the future.
One interesting case of non Dispose objects is when very small managed objects hold large amounts of unmanaged memory (i.e. allocated with some flavor of Win32 memory management functions i.e. HeapAlloc ). In this case managed memory manager may not be able to detect memory pressure properly to trigger Gen2 GC and (especially in case of x86 - 32bit process) it may prematurely fail to allocate managed memory for your process. The other issue in this case is fragmentation of address space by "waiting for GC to be de-allocated" (again mostly in x86 case) - when smaller chunks of native memory are allocated with some relatively large space between them preventing allocation of large blocks needed for managed memory management.
Notes:
This answer explicitly talks about true memory leaks/memory allocation issues cased by not disposing IDisposable object managing memory. While it is true that there are no "true memory leaks" caused by such practice most people will consider growing memory usage as memory leak (similar to storing large amount of objects in static list/dictionary for lifetime of an application).
One can create object that manages native memory and incorrectly implements IDisposable pattern. In this case it is possible to really leak native memory (irrespective of calling Dispose).
In most cases objects that implement IDisposable don't managed memory at all. For most practical C# programs native resources managed by such objects are handles for system resources like files, bitmaps, fonts, synchronization objects or COM native objects. Not disposing them in timely manner will cause other issues.
Dispose all objects properly. There is no excuse not to.
Dispose() is intended to free resources that the garbage collector won't free, such as database connections. These resources should also be freed in the finalizer, however the finalizer is much slower than the Dispose() method.
For me:
Dispose can be used in using() scope. This can help me to determine the lifespan of a IDisposeable component. I usually use this in StreamWriter/Reader or SqlConnection classes.
Another use of Dispose is it can end a lifespan of a component explicitly. Such as calling Form.Dispose() in C# winform will close the form. However, for SqlConnection, people said that just calling Dispose alone without explicitly calling Close won't guarantee the connection to be closed. Advised to call both Close and Dispose. I haven't tried this though.
And another thing, after Dispose() is called, the GC can immediaetly free the memory, because they know that the object lifespan is end, rather than waiting for the lifespan to end.
Similiar question may be C# disposing IDisposable
Can NOT calling Dispose() cause memory leaks?
Yes, of course. Below is just one example.
Assume you have a main window in your application and you create a child control that has an event subscription to the main window. You unsubscribe from them on Dispose. If you don't dispose, main window can hold the reference to your child control until you close the application.
What's the worst thing that can happen if you have a large program and
never call Dispose() on any of your IDisposable objects?
The worse case is not releasing some unwanted memory until you close the application.
And the other question is, what if you never implement IDisposable or finalization when they are required?
The worse case of having a memory leak is holding on to that memory until you restart the PC. This can happen only if you have un-managed resources and you don't implement dispose/finalize. If you implement Idisposable interface and implement the finalizer, finalization process will execute the Dispose for you.
Another reason why you should call Dispose is to Suppress the finalization.
As I've indicated before if there is any object with Finalize method and you didn't call the Dispose. That object can reside in memory for two GC cycles. In the first cycle, it enqueue that instance to the finalization queue and finalization happens after GC process. So, only next GC cycle can release that memory.
I noticed that System.Threading.Thread implements a finalizer but not IDisposable. The recommended practice is to always implement IDisposable when a finalizer is implemented. Jeffrey Richter wrote that the guideline is "very important and should always be followed without exception".
So why doesn't Thread implement IDisposable? It seem like implementing IDisposable would be a non-breaking change that would allow deterministic cleanup of Thread's finalizable resources.
And a related question: since thread is finalizable, do I have to hold references to running Threads to prevent them from being finalized during execution?
What would disposing of a Thread object do? The "resource" in this case has its own natural clean-up - the thread finishing. Note that also the sense of ownership is missing... within the executing thread, you can always use Thread.CurrentThread, so only that thread would really able to claim any sort of ownership.
Basically I think Thread is a slightly unusual case - there's a lifetime to the underlying resource, but it isn't something that ought to be cleaned up explicitly.
That's probably because you can't dispose of a thread. Instead you can ask it to die using Abort() or alike.
This is kind of a design question, so anyone who was not involved in building this aspect of .NET can only speculate. That being said, this blog post makes a good point:
...implementing IDisposable would not make any difference, at least in the current implementation of Thread. I increased the number of threads being created and the handle count goes down at some point so there is some mechanism for closing them
Threads do naturally clean up after themselves, so they are not a resource that needs to be managed in the typical sense.