Click here to Skip to main content
15,892,072 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Dear experts
It looks like I don't get the point on WeakReference. My goal is to let "observe" lifetime of a form by WeakReference.

In my MainForm I create a Formtest using a weak reference:
C#
    public partial class FormMain : Form
    {
        private WeakReference weakRefFormTest= null;

        private void buttonNewForm_Click(object sender, EventArgs e)
        {
            if (weakRefFormTest == null)
            {
		// Create WeakReference and the form
                weakRefFormTest = new WeakReference(new FormTest());
                ((Form)weakRefFormTest.Target).Show();
            }
            else
            {
		// Check form alive  *1)
                Form formTest = (Form)weakRefFormTest.Target;
                if (formTest != null)
                {
                    formTest.Visible = !formTest.Visible;
                }
            }
        }
	...
	......
    }

*1) Here I expect, that (Form)weakRefFormTest.Target will be null after closing the testForm. But it is not like this, it will give me always a "valid" form. Also weakRefFormTest.IsAlive returns true after closing formTest. And using then the form in the code throws an System.ObjectDisposedException

Can you point me out what I do not understand, where I'm wrong?


N.B: I'm aware I could subscribe for Form.Closed-Event, but I don't like this approach.

Thank you very much in advance.

What I have tried:

See code snippet in the question.
Posted
Updated 18-Jul-16 23:05pm
Comments
Hermann Jung 19-Jul-16 5:17am    
WeakReference.Target will be null when the GarbageCollector has collected the Form. Form.Close() does not call GC.Collect() - and you should not do it in your code (see GarbageCollector documentation). You should probably perform another check on Form.IsDisposed.
[no name] 19-Jul-16 5:21am    
Thank you for your comment. Seems I Need to dive depper into all this.
[no name] 19-Jul-16 6:46am    
Yes of course you are right, if ((formTest != null) && !formtest.IsDisposed)) is an acceptable way. I was thinking about something like that, but only searched for a property Disposed. I suggest to post it as a solution :-)

1 solution

Look at the documentation: WeakReference.Target Property (System)[^]
And it states that:
Property Value
Type: System.Object
null if the object referenced by the current WeakReference object has been garbage collected; otherwise, a reference to the object referenced by the current WeakReference object.
Just because it is closed, does not mean that it has been deallocated by the Garbage Collector - remember that the garbage collector is only ever kicked into action when memory runs low, or Dispose is called on an object. Closing a form does neither of those things, or you would not be able to access the content of a form once the user had finished filling it in and pressed "OK":
C#
frmLogin f = new frmLogin();
if (f.ShowDialog() == DialogResult.OK)
   {
   string username = f.UserName;
   ...
   }
If you want to know when a form is closed, you need to use the event, not a weak reference.

[edit]:doh: I need more caffeine...[/edit]
 
Share this answer
 
v2
Comments
[no name] 19-Jul-16 5:14am    
Thank you very much for your speedy reply +5. You write "... or Dispose is called on an object. Closing a form does neither of those things ..." but if I read the MSDN documentation I find "When a form is closed, all resources created within the object are closed and the form is disposed." And that is what led me to believe that WeakRef suitable.
OriginalGriff 19-Jul-16 5:36am    
Sorry - I should have explained more clearly - my mistake.
Dispose is called for a Form when it is closed, and it is responsible for shutting down the Message Loop, deallocating the Windows Handle, and such like resource cleanup.
But Dispose does not deallocate the heap memory for the class - only the Garbage Collector can do that - and it does not call up the Garbage Collector to start the deallocation. It just marks the instance as "disposed" so that the GC doesn't have to call it again when it does decide the instance memory can be released.
If Dispose caused deallocation, then anywhere that a *using* block was used woiuld be unpredictably slow:
using (SqlConnection con = new SqlConnection(strConnect))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT Id, description FROM myTable", con))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int id = (int) reader["Id"];
string desc = (string) reader["description"];
Console.WriteLine("ID: {0}\n {1}", id, desc);
}
}
}
}
Would activate the GC three times! :laugh:
The GC is only called into action when a memory request is unable to be fulfilled, or it is explicitly invoked via GC.Collect.
[no name] 19-Jul-16 5:40am    
Great, thank you again for this! Sorry can't vote more than 5 and also only accept it one time :-)
[no name] 19-Jul-16 5:35am    
And the form is disposed I think, because the exception is System.ObjectDisposedException, right or again a misinterpretation from my side?
OriginalGriff 19-Jul-16 5:38am    
I think he's trying to use a weakreference to tell him when a form is closed - and that means the FormClosed event.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900