I'm writing a Singleton class for access to a List. When the Singleton is first initialized this List is populated by de-serializing an xml file.
This all works great but I want this List to be updatable and in order to do so I'm currently having to re-serialize each time I add or remove from it.
I would prefer to simply have one call to serialize the list when the object is removed from memory. However I feel that trying to do this in the ~Destructor can potentially cause lost data etc.
What is the best pattern to follow to achieve this behavior?
Thanks
Destructors in C# are very different from C++ destructors. They are not actual destructors that are run on fully correct objects which are no longer required, but a last resort measure to deal with unmanaged resources (MSDN):
You should override Finalize for a class that uses unmanaged resources
such as file handles or database connections that must be released
when the managed object that uses them is discarded during garbage
collection.
So it is a bad idea to use Finalizer (Destructor) to interoperate with managed resources, because:
The finalizers of two objects are not guaranteed to run in any
specific order, even if one object refers to the other. That is, if
Object A has a reference to Object B and both have finalizers, Object
B might have already been finalized when the finalizer of Object A
starts.
Deserialized data list may be correct during such finalization, or it may have been already reclaimed during previous GC runs. Even if it is not so with current garbage collector, no one can guarantee that such problem won't appear in the next .NET version. Accessing managed resources in Finalizer's is practically an undefined behaviour.
Possible solution
Taking into account that your object is singleton, and thus it can be garbage collected only when application exits (or never if it is never requested),
the simplest way to allow such persistent storage to object's data is to attach event handler to the application close(exit) event.
...
public static Singleton Instance
{
get
{
if (_Instance == null)
{
_Instance = new Singleton();
Application.Exit += (sender, args) =>
{
_Instance.SaveChanges();
}
}
return _Instance;
}
}
Or use appropriate Lazy<T> constructor if your Singleton is based on its use.
Related
NET for a long time now and have started to learn C#. One thing I suppose I may have asked years ago, got the answer but have completely forgotten it now as it is not something I implicitly use a lot is destructors. As I am going through learning C# I read an article about how to create these in C# however it has left me wondering. Let say I instantiate a class which has an object to another class.
Class C1
{
// Do something here
}
Class A
{
C1 objObjectToClass1 = new C1();
}
Class Main
{
A objObjectToClassA = new A();
}
and I make the object objObjectToClassA to null as I have been lead to believe that is the equivalent to object = nothing in VB.NET.
objObectToClassA = null;
Does this action also destroy objObjectToClass1?
Not as such, no. An object will be reclaimed by the garbage collector some time after it has become eligible for collection. This may be after you clear the last reference to it, but it could already be before if you never need the reference anymore after a certain point. But generally, setting a field where you store the instance to null will help the object becoming no longer reachable and getting reclaimed.
Generally you have no control over when objects are reclaimed by the GC. You can write finalizers which are methods that are called prior to reclaiming an object, but I'd very much not recommend it if you can help it. If you need a predictable way of causing an object to release any resources it might hold on to (what destructors in C++ often do), then implement the IDisposable interface:
class C1 : IDisposable {
public void Dispose() {
// Do cleanup here
}
}
This also enables you to use instances of that class in a using statement, which will call Dispose at the end of its block:
using (var c1 = new C1()) {
// do stuf with c1 here
} // at this point c1.Dispose() is automatically called
The garbage collector knows when there are no references any more to objects, and as far as I know, it even destroys objects that are only referenced by another.
That means that if you dereference objObjectToClassA (set it to null), that both objects will get destroyed, if there are no more references to either of the objects. Simply letting it go out of scope is enough too.
In effect, yes it will also destroy objectToClass1, but not immediately. In this case, setting the variable to null means that your application is no longer using that object, and hence it's eligible for garbage collection. Thinking about it simplistically (I'm sure the GC is smarter than this), once objectToClassA is collected then objectToClass1 is no longer referenced and will also be collected.
Joey's comments about IDisposable are definitely worth bearing in mind; try not to think in terms of finalisers for C# as you don't have control over when they run. Using IDisposable will give you the control that you need in order to tidy up resources.
Destroy is the wrong word, C# (as far as I know) does not have destructors in the C++ sense. No longer used objects are collected/"destroyed" by the garbage collector.
If no other reference to objObjectToClass1 is kept, objObjectToClass1 can also be collected if you set objObectToClassA to null
I always thought that the answer to this was no, but I cannot find any source stating this.
In my class below, can I access (managed) fields/properties of an instance of C in the finalizer, i.e. in ReleaseUnmanaged()? What restrictions, if any, are there? Will GC or finalization ever have set these members to null?
The only thing I can find is that stuff on the finalizer queue can be finalized in any order. So in that case, since the recommendation is that types should allow users to call Dispose() more than once, why does the recommended pattern bother with a disposing boolean? What bad things might happen if my finalizer called Dispose(true) instead of Dispose(false)?
public class C : IDisposable
{
private void ReleaseUnmanaged() { }
private void ReleaseOtherDisposables() { }
protected virtual void Dispose(bool disposing)
{
ReleaseUnmanaged();
if (disposing)
{
ReleaseOtherDisposables();
}
}
~ C()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
In general case - yes, you can. If a class has nonempty finalizer, first time GC would collect instance of this class, it calls finalizer instead (only if you didn't call GC.SuppressFinalize on it earlier). Object instance seen from finalizer looks just like it did last time you touched it. You can even create new (direct or indirect) link from root to your instance and thus resurrect it.
Even if you hold unmanaged pointer to unpinned object and inspect raw memory contents, you shouldn't be able to see partially-deallocated object, because .NET uses copying GC. If an instance is alive during collection, it is either promoted to next generation or moved to completely new memory block along with other instances. If it is not reachable it is either left where it was or the whole heap is released and returned to OS. Keep in mind, however, that finalizers can and will be called on instances of objects that failed to construct (i.e. when was an exception thrown during object construction).
Edit: As for Dispose(true) vs Dispose(false) in well-written classes there shouldn't be much of a difference in the long run. If your finalizer called Dispose(true), it would only remove links from your object to other objects, but since your object is already nonreachable, releasing other instances referenced by your object won't matter their reachability.
For more details on .NET GC implementation details, I recommend C# 5.0 in a Nutshell by Joseph and Ben Albahari.
The GC will never collect any object if there is any way via which any code could ever get a reference to it. If the only references that exist to an object are weak references, the GC will invalidate them so that there's no way any code could ever get a reference to that object, whereupon it will then be able to collect it.
If an object has an active finalizer, then if the GC would collect it (but for the existence of the finalizer), the GC will instead add it to a queue of objects whose finalizers should be run ASAP and, having done so, de-activate it. The reference within the queue will prevent the GC from collecting the object until the finalizer has run; once the finalizer finishes, if no other references exist to the object and it hasn't re-registered its finalizer, it will cease to exist.
The biggest problems with finalizers accessing outside objects are:
A finalizer will be run in a threading context which is unrelated to any threading context where the object was used, but should not perform any operations which cannot be guaranteed to complete quickly. This often creates contradictory requirement that code use locking when accessing other objects, but that code not block while waiting on locks.
If a finalizer has a reference to another object which also has a finalizer, there's no guarantee as to which will run first.
Both of these factors severely limit the ability of objects with finalizers tosafely access outside objects they don't own. Further, because of the way finalization is implemented, it's possible for the system to decide to run a finalizer when no strong references exist, but for external strong references to be created and used before the finalizer runs; the object with the finalizer has no say in whether that happens.
My understanding is that when the GC finds a sub-graph of objects that are no longer accessible (via strong references) from the main graph, it will collect them up and reclaim the memory. My question is concerning the order in which inaccessible objects are deleted. Does this occur as an atomic operation? Are all of the inaccessible objects finalized at once, or does the GC finalize each object one-by-one while the application is still executing? If the objects are finalized one-by-one, is there a particular order that is followed?
If I have an object A that holds a weak reference to object B, then it is clear that A must check if B is still alive before invoking any of B’s instance methods. Now suppose B holds a strong reference to another object C. If B is still alive, am I always guaranteed that C will also still be alive? Is there any possibility that the GC might have marked both B & C for collection, but C is finalized before B?
My guess is that it will always be safe to access C from B (since this is a strong reference). But I would like to confirm this assumption, because if I am wrong I could introduce a very intermittent hard-to-track-down bug.
public class ClassA
{
private readonly WeakReference objBWeakRef;
public ClassA(ClassB objB)
{
objBWeakRef = new WeakReference(objB);
}
public void DoSomething()
{
// The null check is required because objB
// may have been cleaned-up by the GC
var objBStrongRef = (ClassB) objBWeakRef.Target;
if (objBStrongRef != null)
{
objBStrongRef.DoSomething();
}
}
}
public class ClassB
{
private readonly ClassC objCStrongRef;
public ClassB(ClassC objC)
{
objCStrongRef = objC;
}
public void DoSomething()
{
// Do I also need to do some kind of checking here?
// Is it possible that objC has been collected, but
// the GC has not yet gotten around to collecting objB?
objCStrongRef.DoSomething();
}
}
public class ClassC
{
public void DoSomething()
{
// do something here... if object is still alive.
}
}
Yes, if your ClassB has a reference to a ClassC instance via objCStrongRef, then if the ClassB is still alive you don't need to worry about the ClassC evaporating at random. The exception to this is if you write a finalizer, i.e.
~ClassB() { ...}
In there, you should not attempt to talk to objCStrongRef at all; because you can have no clue which object gets finalized first. If ClassC needs something at finalization, it should have a separate ~ClassC() - although in reality finalizer methods are really rare and you shouldn't add them without good reason (unmanaged handles, etc)
Re finalization order: no, there is no particular order followed, because full loops are possible - and it needs to be broken somewhere arbitrarily.
In normal managed methods, you can rely on everything that B refers to with strong references to be alive as long as B is alive. The reference to C from B will be good for the lifetime of B.
The exception is in finalization code. If you implement a finalizer (which should be considered an unusual case, not the norm), then all bets are off within the call chain of the finalizer. Finalizers may not execute for a long time after the GC notices that the objects are no longer referenced by live objects - objects with finalizers tend to hang around a lot longer than "normal" objects, which is another reason not to use finalizers. A finalizer may not execute at all, ever, in extreme panic shutdown corner cases. You can't assume anything about what thread the finalizer will execute on, or what order finalizers will execute in. And you should avoid referring to any reference variables in your object because you don't know if they have already been finalized.
This is all academic though. Your code example doesn't implement a finalizer, so you don't need to worry about the bizzarro finalizer world.
From the "CLR via C#" by Jeffrey Richter:
Furthermore, be aware of the fact that you have no control over when
the Finalize method will execute. Finalize methods run when a garbage
collection occurs, which may happen when your application requests
more memory. Also, the CLR doesn’t make any guarantees as to the order
in which Finalize methods are called, so you should avoid writing a
Finalize method that accesses other objects whose type defines a
Finalize method; those other objects could have been finalized
already. However, it is perfectly OK to access value type instances or
reference type objects that do not define a Finalize method. You also
need to be careful when calling static methods because these methods
can internally access objects that have been finalized, causing the
behavior of the static method to become unpredictable.
If there exists no reference path of any sort which can reach an object, there will be no means to examine the memory space that object used to occupy, unless or until such time as the GC has run and made that memory space usable for reuse and some new object is created that uses it; by the time that occurs, the old object won't exist anymore. Regardless of when the GC runs, an object becomes instantly inaccessible the moment the last reference to it is destroyed or becomes inaccessible.
Objects with active finalizers always have a reference path, since a data structure called the "finalization queue" holds a reference to every such object. Objects in this queue are the last things processed by the GC; if an object is found to be referenced by the queue but by nothing else, a reference will be stored in a structure called the "freachable" queue, which lists objects whose Finalize method should be run at first opportunity. Once a GC cycle completes, this list will be considered a strong rooted reference, but the finalizer thread will start pulling things out of it. Typically, once items get pulled from the list there won't be any reference to them anywhere and they'll disappear.
Weak references add another wrinkle, since objects are considered eligible for collection even if weak references to them exist. The simplest way to regard those as working is to figure that once every object requiring retention has been identified, the system will go through and invalidate every WeakReference whose targets do not require retention. Once every such WeakReference instances has been invalidated, the object will be inaccessible.
The only situation where atomic semantics might matter would be when two or more WeakReference instances target the same object. In that scenario, it might theoretically be possible for one thread to access the Target property of a WeakReference at the exact moment that the GC was invalidating another WeakReference which had the same target. I don't think this situation can actually arise; it could be prevented by having multiple WeakReference instances that share the same target also share their GCHandle. In that case, either the access to the target would happen soon enough to keep the object alive, or else the handle would be invalidated, effectively invalidating all WeakReference instances that hold a reference to it.
Assuming i have the following classes:
Class MainClass
{
private OtherClass1;
MainClass()
{
OtherClass1 = new OtherClass1();
}
void dispose()
{
OtherClass1 = null;
}
}
class OtherClass1
{
private OtherClass2;
OtherClass1()
{
OtherClass2 = new OtherClass2();
}
}
class OtherClass2
{
}
If i instatiate MainClass and later call dispose method, does the OtherClass1 gets garbage collected (later on)? Or do i have first to clear the reference to OtherClass2?
An object will get garbage collected if it has no references, or the references it does have are from objects that themselves don't have references (and so on).
A way of visualising it, is the garbage collector will walk the object reference graph, following all object references, making a note of ones it gets to (still referenced from somewhere). Any it doesn't get to are eligible for garbage collection as if it didn't get to them then they can't possibly be used.
See here for in-depth info (particularly "The Garbage Collection Algorithm"): http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
So yes, it'll be eligible to be GC'd.
Also, if you have a dispose method you really should implement IDisposable.
In the code as provided, you don't have to null anything, you can safely remove your dispose() and all will be well.
If your OtherClass1 and/or OtherClass2 are managed resources, ie they implement the IDisposable interface then your code is not good enough. You then will have to chain the Dispose:
class MainClass : IDisposable
{
private OtherClass1;
MainClass()
{
OtherClass1 = new OtherClass1();
}
public void Dispose()
{
OtherClass1.Dispose();
// OtherClass1 = null; // not needed
}
}
If there is no other reference to it, it may at some time be garbage collected. Note that this is not deterministic, you cannot rely on it being collected in a specific timespan.
In general, you shouldn't worry too much abot this, the GC in .NET can by design handle circular references etc. without any problem. Setting fields to null is usually not required. The Dispose method is usually used to release unmanaged resources, such as database connections etc. in a deterministic fashion; it's not about freeing the memory of the object being disposed.
The best practice is to implement IDisposable interface and implementing the Dispose() method.
At Dispose(), you just release the resources used by your object such as any external resources, COM references, database connections, etc.
In terms of When the object will be garbage collected, it's up to the .NET engine to decide that as they frequently update their disposal algorithm with each release.
In general, when an object is orphan (no variable references it), it will be in the queue to be garbage collected.
You can manually call GC.Collect(); but that's not recommended since it interferes .NET garbage collection mechanism.
The term "Dispose" is a bit of a misnomer, since the Dispose method doesn't delete the targeted object but rather serves a request for the targeted object to do anything that will need to be done before it may be safely abandoned. Essentially, it's a request for the object to put its affairs in order.
The most common situation when a particular object will need to put its affairs in order is when some entities outside of it may be doing something, storing something, refraining from doing something, or otherwise temporarily altering their behavior on its behalf. Note that the entities may be .net objects, other types of OS-recognized objects (GDI handles, etc.), etc. but there's no particular requirement that the entity be any particular kind of thing, nor that they be in the same computer, or even any computer. For an object to puts its affairs in order, outside entities doing, holding, etc. anything on its behalf need to be told that they no longer need to do so. If the entities in question are .net objects that implement IDisposable, the notification would be generally performed by calling their Dispose method.
Note that .net provides a means by which objects can ask to be notified if the system notices that they've been abandoned, and use that as a cue to put their affairs in order. Such notifications may not come in timely fashion, and various factors may cause them to be delayed essentially indefinitely, but the mechanism (called "finalization") is sometimes better than nothing.
How can I make sure that the objects get disposed that I am adding into the SerializationInfo object?
For example: if I am adding a hashtable to the info object, how do I make sure that after serialization, there is no reference alive to the hastable object of my class and I can free the memory somehow?
info.AddValue("attributesHash", attributesHash, typeof(System.Collections.Hashtable));
Update (code)
[Serializable]
class A : System.Runtime.Serialization.ISerializable
{
List<int> m_Data = new List<int>();
//...
public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
{
if (m_Data != null)
{
info.AddValue("MyData", m_Data, typeof(List<int>));
m_Data.Clear();
}
m_Data = null; // <-- Will this be collected by GC?
GC.GetTotalMemory(true); //forced collection
}
};
My question is: if i make my object null after adding to the info list, will it be freed after serialization is called (when info is destroyed - I hope), or in the line when GC's function is called (which I don't think so)?
If setting 'm_Data = null' will not mark it as garbage, then how would I know that the memory occupied by m_Data has been freed or not?
"I can free the memory somehow" and "objects get disposed" do not go along very well.
Memory management is done by the GC. As soon as there is no more reference to an object, it gets flagged for garbage collection. So it deals with managed resources.
Disposing, however, is totall different animal and is calling Dispose() on types implementing IDisposable and deals with unmanaged resources such as file handles and windows resources.
You need to make it clear which you one you mean.
You need to make your containing object implement IDisposable. But just because you have become serialized does not mean that you need to also be disposed. The referencing object should then call dispose after serialization if that is what is expected.
As for the deserialized object, it should also be disposed by whatever references it when it is done being used (presumably in another appdomain?). So what this means is that both instances will need to be disposed. If the resource you share is a single instance (such as an IntPtr) then you might need to be more clever about it, such as not disposing of that unmanaged resource with this object but from a higher level.
General rule of thumb: he who creates it, disposes it.
One other common pattern, as described by the IDisposable documentation is to put a call to Dispose() into your objects destructor. This will give you non-deterministic timing for your disposal but is guaranteed to work (assuming you don't have reference leaks).
After much analysis, I don't think GC collects memory when requested... not in the case of GetTotalMemory function, at least.
Setting the object to null marks it as garbage, but it doesn't mean it will be collected immediately.