none
Cannot access a disposed object RRS feed

  • Question

  •  

    i found an error - cannot access a disposed object in my project.

    i using vs2005.

    but before this, i using vs2003 and this error doesn't occur.

    but when i convert to vs2005 and debug, this error occured.

     

    any one know what this happen?

     

    please advice..........

     

     

    Thanks 1st

    Wednesday, April 18, 2007 1:52 AM

Answers

  • Determine the object that throws the exception during debug, then step through the code from the begining while watching that object.  Find the code that calls Dispose(), or causes Dispose() to be called, on the object.  This is what must be modified to prevent the object from being disposed.  Or, if you don't need a previous instance of the object, reinitialize it right before the line that throws the exception e.g. Object = New Object

     

    -EDIT-

    Also be sure that it isn't part of a conversion error (check the upgrade log file).  You may need to make a modification to the original 03 code before converting to 05.

    Wednesday, April 18, 2007 2:33 AM
    Moderator
  • Once the form has been disposed it must be reinitialized before it can be used in any way.

     

    The call to oForm.Close() will cause Dispose() to be called on the form.  The second call to oForm.Dispose() is not necessary.

    After calling Close() on the form, you must create an instance of a new form before you can use it again:

    Code Snippet

    Dim oForm As New Form

    oForm.Show()

    oForm.Close()

    oForm = New Form

    oForm.Show()

     

     The form object happens to have a special Close() method and this method calls Dispose().  Many other objects also have a Dispose() method that is used for cleanup purposes, but most do not have a Close() or equivelent method.  In these objects it is necessary to call Dispose() explicitly when you are finished with the object.  In the case of the Form, calling Close()  does the cleanup so you don't need to call Dispose().

    Wednesday, April 18, 2007 3:03 PM
    Moderator
  • Hi Khin,

    If you plan to use the Form object later, use Form.Hide() instead of Form.Close(). It will hide the form and not dispose it. Later when you don't want to use it, use Form.Dispose().

    I hope this solves your problem. It worked for me.
    Wednesday, April 18, 2007 4:01 PM

All replies

  • Determine the object that throws the exception during debug, then step through the code from the begining while watching that object.  Find the code that calls Dispose(), or causes Dispose() to be called, on the object.  This is what must be modified to prevent the object from being disposed.  Or, if you don't need a previous instance of the object, reinitialize it right before the line that throws the exception e.g. Object = New Object

     

    -EDIT-

    Also be sure that it isn't part of a conversion error (check the upgrade log file).  You may need to make a modification to the original 03 code before converting to 05.

    Wednesday, April 18, 2007 2:33 AM
    Moderator
  • Thanks for reply.

     

    if my object is a form....

    so is it the dispose method cannot use if the form already been close and open again?

    what i mean here is:

     

    oForm.Close()

    oForm.Disposed()

     

    after that, oForm open reopen again. and then the 2nd time is it the disposed cannot be use?

     

     

    Thank you

    Wednesday, April 18, 2007 9:45 AM
  • Hi

     

    When you dispose of an object you are telling it that it will no longer be needed by your application and that it can free up any resources that it may be holding onto.

     

    To reopen the form, simply create a new instance of it.

     

    Richard

    Wednesday, April 18, 2007 10:57 AM
  • Once the form has been disposed it must be reinitialized before it can be used in any way.

     

    The call to oForm.Close() will cause Dispose() to be called on the form.  The second call to oForm.Dispose() is not necessary.

    After calling Close() on the form, you must create an instance of a new form before you can use it again:

    Code Snippet

    Dim oForm As New Form

    oForm.Show()

    oForm.Close()

    oForm = New Form

    oForm.Show()

     

     The form object happens to have a special Close() method and this method calls Dispose().  Many other objects also have a Dispose() method that is used for cleanup purposes, but most do not have a Close() or equivelent method.  In these objects it is necessary to call Dispose() explicitly when you are finished with the object.  In the case of the Form, calling Close()  does the cleanup so you don't need to call Dispose().

    Wednesday, April 18, 2007 3:03 PM
    Moderator
  • Hi Khin,

    If you plan to use the Form object later, use Form.Hide() instead of Form.Close(). It will hide the form and not dispose it. Later when you don't want to use it, use Form.Dispose().

    I hope this solves your problem. It worked for me.
    Wednesday, April 18, 2007 4:01 PM
  • hi all,

     

    Form.Close()      --> already displose? cause debug until here, u can found that ?Form.handle already throw the expection.

    Form.Dispose()

     

    but why i try and catch with ObjectDisposedException but cant.

    Why? i catching wrong exception?

     

     

    Thanks

    Wednesday, April 25, 2007 9:40 AM
  • Dispose() method is created in such a way that multiple calls to it don't throw any error. If the object is disposed, that does not mean it is removed from memory. It releases the unmanaged resources when disposed, and is like a dead object still living on heap. So, you can call it's methods, but those methods throw ObjectDisposedException by checking perhaps some flag if the object is disposed.But Dispose() method just ignores all the calls after it is called once.

    So, In the given code, if you add Form.Show(); after Form.Close(), you will catch the exception. Hope you understand.
    Wednesday, April 25, 2007 10:10 AM
  • thanks for reply.

    yes, you are right. the error that i catched was after form.close and form.show.

    em. but just ignore its in my program, will cause any problems or issues?

     

    thanks a lot.

    Wednesday, April 25, 2007 10:19 AM
  •  Khin wrote:

    thanks for reply.

    yes, you are right. the error that i catched was after form.close and form.show.

    em. but just ignore its in my program, will cause any problems or issues?

    thanks a lot.



    Sorry, but I can not get you...
    Are you telling that you ignore that exception, then you are doing wrong if the form is an important part of the application.

    Correct me if I am wrong.
    Wednesday, April 25, 2007 10:50 AM
  • hi decyclone,

    ya, you are right.

    but how i free from this exeption?

    i had tested that if i ignore the exeption, actually it wont give any effect on my program.

    but i wonder that this not a correct way to fix this bug.

     

    Thanks a lot.

     

     

    Thursday, April 26, 2007 12:33 AM
  • Even if you ignore this exception, it will still cause a lot of overhead in your program, especially the first time it is caught.

     

    You should never have to catch an exception for a disposed form.  I would definitely fix this if I were you.

     

    Like rkimble has said, you don't need to call dispose after close.  Just call close.

     

    If you close the form, declare a new form again, before you call Form.Show.

     

    Catch all exceptions first, to see what the exception is. (Catch ex as Exception). Once you fix it, you should be able to remove the Try block, and not catch anything.

     

    If you can, post the parts of the code that throws the exception, that would help.

     

     

    Thursday, April 26, 2007 1:54 AM
  • hi Matt

     

     Matt_Fomich wrote:
     

    You should never have to catch an exception for a disposed form.  I would definitely fix this if I were you.

     

     

    what you mean that i should never to catch an exception for disposed form?

    but if the disposed form are throwing exception, i also need to catch it up, right?

    sorry, maybe i not really understand. can you explain more about this?

     

     Matt_Fomich wrote:
     

    Like rkimble has said, you don't need to call dispose after close.  Just call close.

     

    as i know, ya you are right that close already doing the job of dispose but this dispose job doesn't clear actually the memory, rite?

    so is needed to call dispose() to clear all the memory.

    i doing this because i need to make sure that all unnecessaries memory to be clear.

    so i not very sure that if i didn't displose after close will cause any issue to my program.

     

     

    Thanks Matt.   Smile

     

     

     

    Thursday, April 26, 2007 2:27 AM
  •  

     The form's close event automatically calls dispose. 

     

     From MSDN: "When a form is closed, all resources created in the form are closed, and the form is disposed."  

     

     http://msdn2.microsoft.com/en-us/library/system.windows.forms.form.close.aspx Read the remarks section.

     

       The only time I can think of, when you would call dispose, is if you initialize a form, it was never used, and you have code in the Closed event, and you don't want it to fire.  Then you would call dispose, but you would not call close.

     

    the close already doing the job of dispose but this dispose job doesn't clear actually the memory, rite?

     

    No. Calling Close will always clear the memory.  No need to call dispose. 

     

     What you mean that i should never to catch an exception for disposed form?

     

    I mean that closing a form should never throw the exception.  Something is wrong. Closing a form, or disposing a form should never cause an exception.  Why put code in a try block if it will never throw an exception?  There is some overhead involved with using a try block.

     

    I think that the exception you are getting is that somewhere in your code, you are calling dispose, and then calling close. 

     

    You can't call close on a disposed form.

     

    Do a search for "Name_Of_Form.Dispose", and comment out all the lines, and see if it fixes the problem.

     

    Edit: Did you step thru the program, like rkimble said? that's the best way to find out where the problem is occuring.  Problem might also be that form needs to be initialized again, because it was already closed, as someone has pointed out.

     

     

     

    Thursday, April 26, 2007 3:21 AM
  • Create the object when any event fires like this.

     

    Private Sub btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click

    Dim frmViewReportForm As New frmViewReport

    frmViewReportForm.Show()

    End Sub

    Tuesday, May 1, 2007 4:42 AM
  • hi Matt,

     

    yes, i already tried to comment out all the lines that related with dispose method. But as you mention calling Close() already will do the dispose, so the error still occur.

     

    and in other test case i found that maybe is because i already closing the child form in parent form, so when program back to the child form then due to the object already dispose so the error occur. is it will happen? but as i mention that this situation didn't occur any error in vs2003 but just in vs2005.

     

    so... i also don know how to fix this...

     

    please help....

    thanks

    Wednesday, May 2, 2007 2:22 AM
  •  

    "because i already closing the child form in parent form" 

     

    If you closed the child form from the parent form, then the form can't be used again.  It must be re-initialized before you use it again.

     

    , so when program back to the child form then due to the object already dispose so the error occur.

     

    If you know where the exception is being thrown, find the code where the program "goes back to the child form".  Place this before that code, using the names of your Form and Form variable:

     

    '

    If NameOfChild.IsDisposed Then

        NameOfChild = New ChildForm1

    End If

    ' ^^^ Place before the code that causes ObjectDisposedException. 

     

    If you don't know where the exception is happening--have you made a break point, and stepped through the project yet?  It is easy to do, and can show where the exception is being thrown.  To make a break point, locate a line of code to make a break point on, click on the margin on left side of the line of code, and a red dot will appear, indicating a breakpoint. You should put the breakpoint at the beginning of the method that you think is causing the exception.  Then run the project, and the project will pause on the break point, and highlight it with a yellow background.  The break point pauses the code at that point.  When paused, you can press F11, to "Walk" or "step" through the code, one line at a time.  Keep pressing the F11 key, until you locate where the exception is happening.

     

    Here is a link that shows how to Set BreakPoints: http://msdn2.microsoft.com/en-us/library/k80ex6de(VS.80).aspx

     

    I am not really sure if this will help you or not.  To get better help, please post the code that is causing the exception.

     

    Wednesday, May 2, 2007 8:14 AM
  •  

    hi,

     

    1. MainForm

                   a) CloseForm Function - close childform and load childform if task haven't finish else end MainForm.

    2. BaseForm

                   a) CloseForm Function - call MainForm.CloseForm

    3. ChildForm - inherits BaseForm

                   a) Call BaseForm.CloseForm.

     

    so when ChildForm call BaseForm.CloseForm, that mean system will call MainForm.CloseForm and the process in MainForm.CloseForm are:

     

    public sub CloseForm

     

         if not last Task then

                    ChildForm.Close()

                    ChildForm.Dispose() --------> error already occured when checked in Immediate ?ChildForm.Handle

     

                    if Task haven't finish then

                              ChildForm.Show()

         else

                    ChildForm.Close()

                    ChildForm.Dispose()

                  

                    NextChildForm.show()

         end if

     

    due to the recursive method, the flow will be like below:

              1st  ChildForm -> call MainForm.CloseForm (but in MainForm.CloseForm will open a new ChildForm)

                             |

                  2nd     |_ChildForm

                                      |

                         3rd       |_ChildForm

                                              |

                               4th          |_Childform

     

    so the 1st childform only will totaly close when the system really close in 4th childform.

     

    in ChildForm:

     

    public sub ShowForm()

    try

          me.show() ---> will Go toChildForm_Load()

    catch() ------>> error caught here

     

     

    private sub ChildForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

    try

          if something then

               call Baseform.closeForm

               exit

          end if

    catch()

    end sub ---------------------------------> error

     

     

    but when i changed the code above to:

     

    public sub ShowForm()

    try

          if tasks haven't finish then

                  ChildForm_Load(nothing, nothing)

          else

                  me.show() ---> will call ChildForm_Load()

           end if

    catch()

     

    but i not think this is the correct way for this bug, because when i checked the red color the error will have.

     

    please help!....thanks a lot.

     

    Thanks a lot.

     

     

     

    Tuesday, May 29, 2007 1:41 AM
  • Try changing this code here:

         if not last Task then

                    ChildForm.Close()

                     

                    if Task haven't finish then

                              ChildForm.Show()

         else

                    ChildForm.Close()

                    ChildForm.Dispose()

     

     

    First, there is no need to call Childform.Close, and then call Childform.Dispose.  This is a waste of CPU clock cycles.  Please do not do this.

     

                    ChildForm.Close()

                    ChildForm.Dispose()' Dispose. Really? Why? Close automatically calls Dispose. 

     

     

    Also, you are not checking to see if ChildForm was already Disposed.

     

      ChildForm.Close ' No good. What if the child form was already disposed? What if it was set to nothing? What if it was never initialized? This could cause exception.

     

     

    ' Here is better method. 

      If Not Task AndAlso Not ChildForm Is Nothing AndAlso Not ChildForm.IsDisposed Then

          ChildForm.Close()

      End If

     

    Also, calling ChildForm_Load(nothing, nothing) is not as safe as calling ChildForm.Show. Obviously, if you are referencing the Sender, or any event arguments, then this will cause problems.  If there is code that you need to always fire when the form is shown, then make a new sub routine for that code, and call that sub routine before you call form.show. e.g., ChildForm.ResetForm : ChildForm.Show

     

    Let me know if this fixes problem.  If problem not fixed, maybe post all of the code in the method that causes exception.

     

     Regards,

     

    -Matt-

     

    Wednesday, May 30, 2007 3:20 AM
  •  Matt_Fomich wrote:
     

    Obviously, if you are referencing the Sender, or any event arguments, then this will cause problems.   

     

    can you give some example that problems will occur?

     

    i found a way to solve this, but i don know whether is the correct way:

     

    private sub ChildForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

    try

          if something then

               call Baseform.closeForm

               exit

          end if

    catch()

    end sub ---------------------------------> error

     

     

    but when i changed the code above to:

     

    public sub ShowForm()

    try

     

    /*remove

         if tasks haven't finish then

                 ChildForm_Load(nothing, nothing)

          else

                  me.show() ---> will call ChildForm_Load()

           end if

    */

     

    if something then

               call Baseform.closeForm

               exit

    else

         me.show

    end if

    catch()

     

    i do Baseform.closeform in showform function not in childform_load

    then the error won't show, but i still could catch that error if i debug it in Immediate.

     

    please advice....

     

    thanks a lot...

    Thursday, May 31, 2007 4:22 AM
  •  

    can you give some example that problems will occur?

     

     There are normally 2 arguments, for every form load--the sender object, and the event arguments, e.

    If you never reference the sender, or the event arguments, then you should not have any problems calling Form_Load, instead of Form.Show.  Here are some things you can't do:

     

    Private MyCustomEventArg As New EventArgs

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Select Case DirectCast(sender, Button).Name

      Case "Button1"

          If e Is MyCustomEventArg Then

              ' do something with the event, blah blah blah

          End If

      End Select

    End Sub

     

    You can't get any info on the sender, or event args, because you are using "Nothing", for the sender, and "Nothing" for e.  I don't think that will be a problem for you, because no one really does this on a form, this is normally done for dynamic menu items, context menus that you create and fill on the fly.

     

    Anyway you can call ChildForm_Load(Nothing, Nothing).  That is OK to do, if that fixes your problem.

     

     Just make sure to put a comment over the load event that this sub routine is sometimes called directly, with no arguments for the sender and event.

     

    Anyway, if you still have an exception, then post all of your code that causes exception, along with ex.ToString, and ex.StackTrace. 

     

    There are some really smart people on this forum, and more info would make it easier to fix.

     

     

    Regards,

    -Matt-

    Thursday, May 31, 2007 9:18 AM
  • hi,

     

    thanks a lot...

     

     

    Wednesday, June 6, 2007 3:43 AM
  • Here's a workaround if you want to be able to show a form multiple times.  The window's built in X at the top right calls close() which will call dispose().

    You can override the FormClosing event, cancel the close, and then call Hide().  You can Show() the form over and over at this point.

    private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel =
    true;
        Hide();
    }



    Seems like this was intended to save us the "hassle" of freeing the form ourselves.
    Wednesday, September 10, 2008 5:15 PM
  • I'm sorry:

    > You can Show() the form over and over at this point.

    This is not true! Read MSDN:

    > When a form is closed, all resources created within the object are closed and the form is disposed. You can prevent the closing of a form at run time by handling the Closing event and setting the Cancel property of the CancelEventArgs passed as a parameter to your event handler. If the form you are closing is the startup form of your application, your application ends.

    This is not true! See next code:

     

     public partial class FormMain : Form
     {
      private static FormHint _formHint = new FormHint();
    ...
      private void FormMain_Shown(object sender, EventArgs e)
      {
        /// if (_formHint.Handle != (IntPtr)0)
        ///  _formHint.Tag = 0;
        Program.OnReceiveMessage += new ReceiveMessageHandler(_formHint.DoReceiveMessage);
        CheckMessagesChatBuffer();
        _formHint.Show ///<-- Is disposed form exception.
      }
    
      public void CheckMessagesChatBuffer()
      {
        if (Program.chatsViewer.ChatBuffer.Count == 0)
        {
         //// not check - if (_formHint.Visible) 
         _formHint.Close();
    ...   
    }
    }

     private void FormHint_FormClosed(object sender, FormClosedEventArgs e) { Program.OnReceiveMessage -= new ReceiveMessageHandler(_formHint.DoReceiveMessage); } private void FormHint_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = true; }

     

    When I have uncommented code:

     

    if (_formHint.Handle != (IntPtr)0) _formHint.Tag = 0;
    

     

    events closing and events closed alway call. And, I don't have exception. Another full silent kill object with crash delegates.

    Seems, MSDN or .NET 4.0 is not corrected. Because conflict of declaration with release.


    Tuesday, May 31, 2011 6:00 AM
  • RSin,

    This is a Visual Basic forum so pleas don't abuse this forum by dropping C# code in it, as well this thread is 4 years old so it makes not much sense anymore.

    For those who see your reply now when searching.

    The problem is always that by many is misunderstood that the Dispose method does not dispose objects but does dispose the unmanaged resources from an object (pens and more of those things) and sets an object to unusable.

    The releasing of an object is done by the GC at a non predictable time.

     


    Success
    Cor
    Tuesday, May 31, 2011 6:23 AM

  • Cor,

    Thank You, I have understood-has seen problem. But I love predictable behaviour. In my event comfortable to create handle beforehand. It for fast showing, fast access and guaranteed events. C# young and did not understand with method dispose. For example:

    System.IO.Compression.GZipStream

    Make full Flush() in method Dispose. But GZip.Flush() is not worked. I use delphi 16 years old. And me strangely incomprehensible many belongings. Once again Thank You.

    Tuesday, May 31, 2011 6:56 AM
  • So, if you did this:

    Form1 oForm = new Form1();

    oForm.Show();

    oForm.Dispose();

    oForm.Show();

    - then it wouldn't work because it was disposed, and the variable no longer holds any values / meaning to it. That's the best explanation I can provide, Khin :)


    Micah P.

    Thursday, December 5, 2019 4:57 AM