C# Delete Instance of Class? - c#

I am sort of new to C# and I have a quick question about instances of classes.
I was told that using only "null"on an instance of a class isn't enough to delete an entire instance and all it's resources, such as pointers, etc. So I have:
ClassHere myClass = new ClassHere() and myClass = null
I really must be thinking about this too hard... I'll give an example as to figure out how exactly the GC works.
Let's say we have 3 instances: x1, x2, x3. Each instance would be mapped to a variable: ClassHere myClass = new ClassHere() except you'd have x1, x2 and x3 instead of myClass.
Then say instances x2 and x3 make some sort of reference to x1. Let's say that x1 does nothing after being referenced by x2 and x3. The GC would only pick up x1 after x2's, and x3's references of x1 would be removed, correct?
If it picks it up even with those references. How would the GC know whether or not I actually need instance x1 which is referenced by x2 and x3 instead of deleting it?
Or am I missing something here?

Well, the only way to destroy a class is to remove it from your source tree :D You can, though destroy instances of a class.
Unlike C++, C# doesn't have deterministic destructors. An object instance becomes eligible for garbage collection when the object instance becomes unreachable. That can happen by virtue of
all references to it being released (e.g., variable going out of scope), or
all references to it being themselves unreachable (e.g., the object instance is references in a collection, and the collection is itself unreachable.
When and if an object instance is garbage-collected depends on memory/resource pressure within the app domain (process). When the app domain ends, though, everything is garbage collected.
Usually you want to make things that matter implement IDisposable, so non-managed resources held can be deterministically released via using blocks and the like.
This is a simplistic answer, but the gist of it is: don't sweat it.

Any of your managed resources you don't need to worry about "deleting". The Garbage Collector will take care of this for you. You only need to worry about cleanup in the case where you are using unmanaged resources(Which I'm assuming you aren't as you don't mention it).
You do not need to null out variables for the GC to collect it.
Here's a link I found on a related stackoverflow question that might help:
http://blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048149.aspx

If the code is running on a server GC isn't going to deallocate the object- unless you restart the server every half hour- seems like a legitimate question to me... I had a similar problem- detecting when a user shuts the browser as opposed to manually logging off the website- my solution was to create an instance for user with a timer and a flag that is set to true via ajax and reset to false by server side timer. But there was a potential for memory leaks- since there was no guarantee instance of the user was being deallocated when they would be automatically logged off.
So I create a class user outside webservice like this and instantiated a list of type user:
class WebService{
public static List<user> UserLoglist = new List<user>();//list of logged in users
[WebMethod(Description = "Per session Hit Counter", EnableSession = true)]
public void ClnUpdateFlag(string un)//gets called via ajax
{//Updates the flags i
//update users status
WebService.UserLoglist.Find(y => y.username == un).isLoggedin = true;
}
}
public class user
{
public string username;
public System.Timers.Timer timScheduledTask = new System.Timers.Timer();
public bool isLoggedin = true;
public user(string puser)
{
username = puser;
setimer(); //set server side timer
}
void Timer1_Tick(object sender, EventArgs e)
{
...
if (isLoggedin)// window is still open
isLoggedin = false;
else// user closed the window
{
...
WebService.UserLoglist.RemoveAll(x => x.username == username);// instance is deleted here
...
}
}
}
void setimer()
{
timScheduledTask.Interval = 3000;
timScheduledTask.Enabled = true;
timScheduledTask.Start();
timScheduledTask.Elapsed +=
new System.Timers.ElapsedEventHandler(Timer1_Tick);
}
}
}
class login{
...
public void Logon_Click(object sender, EventArgs e)
{
if (Membership.ValidateUser(UserEmail.Text, UserPass.Text)){
...
WebService.UserLoglist.Add(new user(UserEmail.Text));// instance of the user is instantiated here
}
...
}
}

Related

In c# how to know if a weak referenced object is going to be garbage collected?

Suppose I have such code:
class Test
{
WeakReference m_ref;
public Test()
{
Test1();
Test2();
}
void Test1()
{
m_ref = new WeakReference(new object());
}
void Test2()
{
// If I do the GC then the m_ref.Target is null
// GC.Collect();
Debug.Log(m_ref.Target);
}
}
void TestFunc()
{
new Test();
}
In this example I created a new object instance and set it to a WeakReference instance in Test1. If I understand correctly after exit the Test1 there would be nothing referenced to the object instance so this instance would be GC soon.
However, in the Test2 if GC is not performed I can still access the object instance via m_ref.Target.
Is there any way I could know that the m_ref.Target is invalid without manually perform the GC?
Nope, you can't. By design, WeakReference is tightly coupled to the garbage collector. Even the documentation mentions it:
Gets an indication whether the object referenced by the current WeakReference object has been garbage collected.
As far as I know, there's no way in C# to know whether there's still alive references to a given object, except maybe manually browsing the whole reference tree (and pretty much reimplementing the GC yourself).
Is there any way I could know that the m_ref.Target is invalid without manually perform the GC?
It is not invalid until the GC collects the object. The point of garbage collection is that you don't know and you don't have to take care of when the object is going to be discarded.
In your example, yes, you are right that after m_ref = new WeakReference(new object()); is executed, the instance will be collected 'soon'. However, 'soon' is not defined specifically whatsoever, so you cannot presume this will happen before Test2 is invoked and Debug.Log(m_ref.Target); executed.
If I understand correctly after exit the Test1 there would be nothing referenced to the object instance ...
You are wrong. Technically you don't have any reference of created object, it may be gc'ed on the next line.
Consider this simple example:
class Program
{
static WeakReference _ref;
static void Main(string[] args)
{
Test();
GC.Collect();
Console.WriteLine(_ref.IsAlive); // false
}
static void Test()
{
var obj = new object();
_ref = new WeakReference(obj);
GC.Collect();
Console.WriteLine(_ref.IsAlive); // true
}
}
In Test() we have strong reference to an object, it indeed persist until end of method.
You can do something like this to be sure
object obj = _ref.Target;
if (obj != null)
{
... safe to do something with obj
}
You can not tell if a WeakReference is valid. But you can tell if it is invalid.
I know that is strange. If I have code that does an if statement and could ask "is it valid" then it could be invalid on the next line of code, so it is useless.
The TryGetTarget call on WeakReference gets a reference to the object, or fails and returns false.
Once it has a reference, the reference prevents the object from being garbage collected, so it will stay valid at least as long as you have the reference.
In some code one might be keeping a List<WeakReference<MyNiftyClass>>
One great way to keep track of that list and keep it clean of unreferenced (elsewhere) references is to have some for loop scan the list with TryGetTarget and if it fails remove the stale reference from the list.
But a removal like that wrecks the iterator so you want to use RemoveAll with a predicate.
I have a class called CognateBase and a static global list called AllCognateBases.
The CognateBase has a Tick() function I call every time tick of the program.
The Tick loop is a good place to reap stale references. So I have...
public static void TickAll()
{
// This will loop through all CognateBase objects and call their Tick, or if deleted from memory, remove the CognateBase.
AllCognateBases.RemoveAll(_TickIfAble);
}
And then the _TickIfAble is
private static bool _TickIfAble(WeakReference<CognateBase> r)
{
CognateBase cb;
if (r.TryGetTarget(out cb))
{
cb.Tick();
return false;
}
else
{
return true;
}
}
Thus the CognateBase instances that are valid get ticked, and the ones that are not valid any more get removed. And because it is in RemoveAll there is no iterator to get messed up.
Anywhere else in the code where I have a reference to a CognateBase and set it to null, the CognateBase will eventually get deleted and removed from the list.
And this test works. All those GC calls are to force Garbage Collection to happen NOW not some time later when C# feels like it.
public static void UnitTest()
{
Debug.Assert(AllCognateBases.Count == 0);
CognateBase b1 = new CognateBase();
Debug.Assert(AllCognateBases.Count == 1);
CognateBase b2 = new CognateBase();
Debug.Assert(AllCognateBases.Count == 2);
GC.Collect();
Debug.Assert(AllCognateBases.Count == 2);
b1 = null;
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
TickAll();
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
Debug.Assert(AllCognateBases.Count == 1);
b2 = null;
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
TickAll();
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
Debug.Assert(AllCognateBases.Count == 0);
}
And the creator...
public CognateBase()
{
AllCognateBases.Add(new WeakReference<CognateBase>(this));
}
WARNING - WHen a reference is set to null like the above b1 = null; the objects may not get garbage collected for a looooooong time. All that time it is still valid and will get it's Tick called!

Dictionary with a class as the value.

I have a small class that I use as the value in a dictionary. When I delete the dictionary will it also destroy the class instance?
class Program
{
class Test
{
public string A_String;
public string B_String;
}
static Dictionary<int, Test> _dict = new Dictionary<int, Test>();
static void Main(string[] args)
{
for(int X = 0; X <=5; X++)
{
Test _test = new Test();
_test.A_String = "A" + X.ToString();
_test.B_String = "B" + X.ToString();
_dict.Add(X, _test);
}
_dict.Remove(2);
}
}
No. You can access test as long as it is in scope.
But since each instance of test goes out of scope after each cycle of the for loop, you can't get to it if you remove it from the dictionary.
static void Main(string[] args)
{
for(int X = 0; X <=5; X++)
{
Test _test = new Test();
_test.A_String = "A" + X.ToString();
_test.B_String = "B" + X.ToString();
_dict.Add(X, _test);
// each _test goes out of scope here
}
_dict.Remove(2);
// Removed from dictionary, have no way to access it now.
I have assumed your question is about whether you can access it. If it is about "deletion" in the unmanaged memory sense, forget it, there is no deterministic deletion, that's what garbage collectors are for.
When I delete the dictionary will it also destroy the class instance?
The garbage collector, which is responsible to dispose the object from the memory, will CONSIDER the object a candidate for collection when all references to that object are gone. In your example when you remove the second element from the dictionary _test is not referenced anymore, as you defined and instantiated it within the for loop scope. Then it should become a CANDIDATE for collection.
From the MSDN on when the garbage collector executes:
Garbage collection occurs when one of the following conditions is
true:
The system has low physical memory.
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.
when control flow exits from Main or any other method where you define and use the dictionary, .Net Garbage collector knows that such dictionary and all items in the dictionary are no longer used. And when GC runs next time it will potentially clean them up. However, you need not worry about whether they are cleaned up or not. As long as they are instance variables, they will surely be cleaned up once they go out of scope.

Special case lifetime analysis

Suppose I have
void foo () {
Bar bar = new Bar(); // bar is never referred to after this line
// (1)
doSomethingWithoutBar();
}
At (1), is the object bar is pointing to eligible for garbage collection? Or does bar have to fall out of scope as well? Does it make a difference if GC.Collect is called by doSomethingWithoutBar?
This is relevant to know if Bar has a (C#) destructor or something funky like that.
Objects can become eligible for garbage collection as soon as it's certain that they will no longer be used. It's entirely possible that bar will be garbage collected before the variable goes out of scope.
Proof:
using System;
class Bar
{
~Bar() { Console.WriteLine("Finalized!"); }
}
class Program
{
static void Main(string[] args)
{
Bar bar = new Bar();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
}
Run in Release Mode (because it doesn't get collected in Debug Mode).
Output:
Finalized!
Press any key to exit...
It also works on ideone which uses Mono. The output is the same.
From a quick reading of the spec, it looks like it's implementation specific. It's allowed to garbage collect it, but not required to.
I get this from a note in section 10.9 "Automatic Memory Management" of the ECMA Spec:
[Note: Implementations might choose to analyze code to determine
which references to an object can be used in the future. For
instance, if a local variable that is in scope is the only existing
reference to an object, but that local variable is never referred to
in any possible continuation of execution from the current execution
point in the procedure, an implementation might (but is not required
to) treat the object as no longer in use. end note]
Emphasis mine.
Without defining what version of the CLR you're referring to, it's impossibledifficult to be definitive about the behaviour that you'll see here.
A hypothetical CLR could, in this example, assuming that the following is true:
The constructor for Bar does nothing
There are no fields that are initialised (i.e. there are no potential side-effects to the objects construction)
Entirely disregard the line Bar bar = new Bar(); and optimise it away as it "does nothing".
As far as my memory serves, in current versions of the CLR bar is eligible for garbage collection the moment after you've constructed it.
Marc answered the question, but here is the solution:
void foo () {
Bar bar = new Bar(); // bar is never referred to after this line
// (1)
doSomethingWithoutBar();
GC.KeepAlive(bar); // At the point where you no longer need it
}
This can definitely occur. For instance, here is a demonstration that an instance can be finalized while you are still executing its constructor:
class Program
{
private static int _lifeState;
private static bool _end;
private sealed class Schrodinger
{
private int _x;
public Schrodinger()
{
//Here I'm using 'this'
_x = 1;
//But now I no longer reference 'this'
_lifeState = 1;
//Keep busy to provide an opportunity for GC to collect me
for (int i=0;i<10000; i++)
{
var garbage = new char[20000];
}
//Did I die before I finished being constructed?
if (Interlocked.CompareExchange(ref _lifeState, 0, 1) == 2)
{
Console.WriteLine("Am I dead or alive?");
_end = true;
}
}
~Schrodinger()
{
_lifeState = 2;
}
}
static void Main(string[] args)
{
//Keep the GC churning away at finalization to demonstrate the case
Task.Factory.StartNew(() =>
{
while (!_end)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
});
//Keep constructing cats until we find the desired case
int catCount = 0;
while (!_end)
{
catCount++;
var cat = new Schrodinger();
while (_lifeState != 2)
{
Thread.Yield();
}
}
Console.WriteLine("{0} cats died in the making of this boundary case", catCount);
Console.ReadKey();
}
}
In order for this to work, you need to emit a Release build and run it outside Visual Studio (as otherwise the debugger inserts code that prevents the effect.) I've tested this with VS 2010 targetting .NET 4.0 x64.
You can tweak the iterations on the 'keep busy' loop to impact the probability of the Cat winding up finalized before its complete construction.

Implementation of BeginUpdate and EndUpdate

1) I'm working on a project and I saw this piece of code, I don't understand what is the point of the Monitor.Lock statement. Can someone explain what its trying to do?
2) the postscript underscroll in the parameter name is really annoying, anyone else seen this naming convention?
public class FieldsChangeableHelper<T> : IFieldsChangeable<T>
{
object _lock;
int _lockCount;
FieldChanges<T> _changes;
public FieldsChangeableHelper()
{
_lock = new object();
_lockCount = 0;
}
public void AddChange(T field_, object oldValue_)
{
if (_changes == null)
_changes = new FieldChanges<T>(field_, oldValue_);
else
_changes.AddChange(field_, oldValue_);
if (RaiseEvent(_changes))
_changes = null;
}
#region IFieldsChangeable Members
public void BeginUpdate()
{
if (System.Threading.Interlocked.Increment(ref _lockCount) == 1)
Monitor.Enter(_lock);
}
public void EndUpdate()
{
if (System.Threading.Interlocked.Decrement(ref _lockCount) == 0)
{
FieldChanges<T> changes = _changes;
_changes = null;
Monitor.Exit(_lock);
RaiseEvent(changes);
}
}
protected bool RaiseEvent(FieldChanges<T> changes_)
{
if (_lockCount == 0 && Changed != null && changes_ != null)
{
Changed(this, changes_);
return true;
}
return false;
}
public event FieldsChanged<T> Changed;
#endregion
}
Monitor.Lock locks the portion of code when multiple thread tries to execute the same piece in parallel. It is made to ensure that only 1 guy is altering/executing the context. Look at the MSDN.
Although its best practice that the locking object is always static, but in your case it is not. Which might pose some problem if your instantiating multiple objects on an open type.
Note one thing, in generics static on open T is different for different type, i.e static member in an Open Type class in your case is different for T i.e DateTime, string, etc.
In csharp, private members of a type are usually named with prefixed _
The way i read it: BeginUpdate() ensures that the current thread calling has exclusive access to the instance and that change events practically will be batched and raised once EndUpdate is called. The author wanted to deal with recursion by itself (e.g. calling BeginUpdate() on the same thread multiple times) and a mechanism to batch UpdateEvents untill after the lock has been released. Because, there is a potential deadlock when raising Events when you still have a lock on yourself. event subscribers might want to access your members and therefore have to lock the sender instance which is already locked.
The whole conditional locking is not required (if my analyses is correct ofcourse) since locks based on the Monitor class are recursive and counted.
There is another problem with the locking mechanism, that is: currently when one thread holds a lock. The second thread wont even wait for the lock but will simply continue without a lock since the lock is conditional! this seems like a big bug!
Regarding the naming convention. I use it myself for a way of differentiating privates from parameters and locals. Its a preference which many C# coding conventions recommend. This helps in a case like this:
void Method(int number)
{
// no need to refer to this since:
//this.number = number;
// can be replaced with
_number = number;
}

List<T>.Clear - Does it have to be called?

So I've been fighting another memory problem in my project for the past week. I tried a couple of memory profilers but nothing gave me insight into what was causing the minor memory leak. The following code turned out to be causing it:
private void DeleteAll( FlowLayoutPanel flp)
{
List<ImageControl> AllList = GetAllList(flp);
List<ImageControl> LockedList = GetLockedList(flp);
for (int i = 0; i < LockedList.Count; i++)
{
AllList.Remove(LockedList[i]);
}
flp.SuspendLayout();
for (int i = 0; i < AllList.Count; i++)
{
flp.Controls.Remove(AllList[i]);
}
DisposeList(AllList);
flp.ResumeLayout();
}
In the code, ImageControl is a UserControl, and the entire method above just removes ImageControls from a FlowLayoutPanel. The DisposList() method just calls ImageControl.Dispose() for all the controls in the list passed to it.
Now, I thought that once this method had exited, AllList would be out of scope and hence all its references to the ImageControl's would be nonexistent. So the GC would do it's stuff. But it wasn't. I found it requires
AllList.Clear();
added to the end of the DeleteAll() method, before AllList was out of scope.
So do you have to always explicitly clear a generic list to free up resources? Or is it something I'm doing wrong above? I'd like to know since I'm making fairly heavy use of temporary Lists in this project.
Ok, here's the GetAllList method. Doesn't look like a problem to me:
private List<ImageControl> GetAllList(FlowLayoutPanel flp)
{
List<ImageControl> List = new List<ImageControl>();
for (int i = 0; i < flp.Controls.Count; i++)
{
List.Add((ImageControl)flp.Controls[i]);
}
return List;
}
BTW, if you see my last couple of topics here I've been fighting memory leaks in my quest to become a proficient c# programmer :) I added the DisposeList() method since I've read Dispose() should be called on any object that implements IDisposable, which UserControl does. I also needed a way to fix up a "bug" with the ToolStrip class (which ImageControl contains), where it causes resources to remain unless the Visible property is set to false before it's destroyed. So I've overridden the Dispose method of ImageControl to do just that.
Oh, and DisposeList() also unsubscribes from an event handler:
private void DisposeList( List<ImageControl> IC )
{
for (int i=0;i<IC.Count;i++)
{
IC[i].DoEvent -= ImageButtonClick;
IC[i].Dispose();
}
}
If AllList were the only reference to the list and the elements in the list, then the list and all its elements would become eligible for garbage collection as soon as you exit the DeleteAll method.
If calling AllList.Clear() makes a difference, then I would conclude that there is a reference to the same list being held elsewhere in your code. Maybe a closer look at the GetAllList() method would give a clue where.
You shouldn't have to clear the list. Can you share your GetAllList() function? The fact that you even need a corresponding "DisposeList()" method tells me there are probably side effects there that keep a reference to your list somewhere.
Also, I'd simplify that code like this:
private void DeleteAll( FlowLayoutPanel flp)
{
var UnlockedImages = flp.Controls.OfType<ImageControl>().Except(GetLockedList(flp));
flp.SuspendLayout();
foreach (ImageControl ic in UnlockedImages)
{
flp.Controls.Remove(ic);
}
flp.ResumeLayout();
}

Categories

Resources