Morten on GIS and .NET
Main interests are OGC standards, GPS and SOAP Webservices.
All projects are based on Microsoft’s .NET technologies.
Main interests are OGC standards, GPS and SOAP Webservices.
All projects are based on Microsoft’s .NET technologies.
The PocketGPSLib for your Pocket PC, makes it easy to implement a GPS receiver in your .NET Compact Framework applications. Written 100% in C#.
Supports RMC, GGA, GSA, GLL and GSV NMEA sentences. The library runs in it's own thread and is asyncronous / event based for easy implementation. Features full support for sending RTCM messages to the GPS device, making Differential GPS possible. PocketGpsLib is released under the GNU General Public License.
For more info and download visit http://gps.iter.dkSharpMap is a simple-to-use map renderer that renders GIS vector, raster and WMS data for use in web and desktop applications.
The engine is written in C# and based on the .NET 2.0 framework. SharpMap is released under the GNU General Public License.
For more info and download visit http://sharpmap.iter.dkGC Truth: setting an object's reference to null will sometimes allow the GC to collect it sooner.
As much as you may want to, you can't guarantee the GC will collect what you want, when you want it to. The best you can do is give it hints. The GC typically does collections when an allocation fails, not necessarily as soon as you're done with an object.
Consider the following method. What is the earliest point the GC could collect the Object that obj references?
void Foo() { Object obj = new Object(); Console.WriteLine(obj.ToString()); for (int i=0; i<10; i++) { Console.WriteLine(i); } obj = null; }
The answer depends on whether you've compiled it in Debug or Release mode. In Debug, the JIT extends all references' lifetimes to the end of their scope. This is so you don't have to worry about the GC cleaning up a variable you're trying to inspect!
In Release mode, the Object is actually first eligible for collection after the call to ToString(). The JIT is usually smart enough to realize that obj = null can be optimized away. That leaves obj.ToString() as the last reference to the object. So after the call to ToString(), the obj is no longer used and is removed as a GC Root. That leaves the Object in memory orphaned (no references pointing to it), making it eligible for collection. When the GC actually goes about collecting it, is another matter.
So when does setting a reference to null allow the object in memory to be reclaimed sooner?
Consider instance variables. Imagine a class that contains a large array of a managed type. There could be times where you no longer need that array, but you want the object to hang around. This is a good case for the Dispose pattern:class BigObject : IDisposable { int[,] array = new int[1024,1024]; public void Dispose() { array = null; } }
Now the GC will clean up the array when it does its next collection, and you can keep that BigObject around for whatever reason, and not worry about it taking up so much memory.
Dispose is just a method, like any other. Its purpose is allow deterministic resource cleanup, much like C++’s destructors, but without freeing the object’s memory. Like a C++ destructor, the developer puts whatever cleanup code is necessary to be performed when the object’s lifetime is up. Unlike a destructor, the object lives on after being "disposed of". This means an object may be in an invalid state after being disposed, and developers should consider using ObjectDisposedExceptions when methods in a disposed object are called.
What happens when you call Dispose()
Any cleanup your object need done in a timely fashion should be done in Dispose. Things like closing database connections, closing files, releasing bitmaps, etc. Unmanaged resources in particular should be released in Dispose. This is because the GC has no knowledge of anything not allocated on the managed heap. For example, a Bitmap object that encapsulates a 2MB image file reports only its managed size (the size of the managed object) to the GC. The GC knows nothing about the 2MB unmanaged image, thus will not collect it from memory. By calling Dispose, you tell the Bitmap object that you are finished with it, and it will release the image itself.
What about the finalizer?There are a few reasons why not to rely on the finalizer to clean up resources that I’ll cover in a future blog entry on finalizers. The main reasons you should be concerned with are performance and determinism. Finalizers are expensive to run, and there’s no order (or even guarantee) that they will be run (for example, the finalizer thread may time out, or be killed on AppDomain unload).
That being said, the finalizer should be your last chance to clean up resources, in case someone using your class forgets to dispose of it when done. A call to Dispose inside the finalizer reduces duplication of code. However, you want to make sure the resources don’t get released twice. In your Dispose method, you want to make sure you call GC.SuppressFinalize(this) after your clean up code. If you suppress the finalizer before the clean up, you’re limiting your ability to recover from failures during the cleanup.
Some of you may have noticed a race condition in my description above. Consider a situation where the call to Dispose is the last time your object is being referenced. As soon as Dispose is entered, the object is eligible for collection by the GC. Before that happens, the object’s finalizer gets called, which calls Dispose. You now have two threads inside Dispose, possibly double-freeing resources (this could be bad, as in the case of GCHandles). Make sure you follow the pattern I linked to above and use a disposing flag to avoid problems like this.