Cannot Access Disposed Object. *FORM ERROR*

Element6

Well-known member
Joined
Feb 16, 2010
Messages
85
Programming Experience
5-10
This is just an FYI; because I got so many hits on google for it.

I got the "infamous" 'Cannot Access Disposed Object.' error when I was attempting to open a form again after I had closed it.

The fix (even though it's annoying), is easy enough; but again it's managed code problems and weirdisms I still haven't changed my opinion that I won't be using MS .NET after this when I get my development box back to normal. BUT anyway the solution is self explanitory and very easy (and somewhat obvious)

VB.NET:
        Dim SomeForm = New Form1
        If SomeForm.IsDisposed Then Return
        SomeForm.Show()

I think what happens (without indepth knowledge of how 3.5 managed code is working.) The "variable" name declaration is associated to some pointer; and the pointer is either A not being used as the lookup and the Variable Name is, or B the collection is overriding the active declaration and not updating the Garbage Collection.

I know this because this code doesn't work.

VB.NET:
        Dim SomeForm = New Form1
        SomeForm.Show()

When it gets to
VB.NET:
        SomeForm.Show()
the Application hickups with a very nice message, after you close the form down and try to reopen it, that says :
Cannot access Disposed object.

So, my thought is that the "IsDisposed" property runs some sort of function to determine the Garbage Collection state and does a collection, or updates the request for the collection to be done.

Either way, an FYI and heads up for a rather annoying little problem.
 
The OS assigns a handle to each window it displays. When you close a .NET Windows Form you dispose it, which releases that handle back to the OS. The form still exists in memory so you can still access it but you can't show it again because it has no handle. If you want to show another form you have to create another form. That's the way it is and that's the way it's supposed to be. Noone is keeping this fact a secret so you might want to do a bit more research.
 
I knew that it was associated; and I knew there was a pointer.

Why do I have to query to see if the thing is disposed; It's not like I can "undispose" an object that has released it's Pointer / Handle; so why should I have to query if it?

This is constant in the framework; the Dim New should have been enough to allow the New "Handle" / Pointer and Override the Assignment; in cases where code would step on each other; it should override it still - and float an ambigious Handle and make it into a broken link. Honestly, it's much easier to handle broken associations then it is to manage associations on the fly.

Broken Associations can be identified by the "managed resources"; what does the program care. I don't like the fact that .NET tries to override how to do programming from a managed state; that is a seperate issue and should be handled as such.

Seriously, if people write bad code - then let it be bad code; .NET is good in the sense that it tries to make everyone that develops a good programmer but in the end it just dumbs down the masses and makes for sloppy business. Just my opinion.

Thank you for your input and yes I "should" do more research - but sometimes when you attack a problem blindly; you get a much better understanding.

As usual, you always have good comments. Not being conflictive, just an old salty developer. As usual for RAD development Microsoft has done well, but as for "technically"; I think they are moving towards the Apple philospophy - and I won't be with them.
 
This work consistently:
VB.NET:
Public Class Form1
    Private SomeForm As SomeForm

    Private Sub Button1_Click (...) Handles Button1.Click
        m_SomeForm = New SomeForm
        With m_SomeForm
            If .ShowDialog(Me) <> System.Windows.Forms.DialogResult.Cancel Then
                'Some code
            End If
            .Dispose()
        End With
    End Sub

End Class
The only other thing that I may have to do outside of this type of structure is checking that it's not nothing, like:
VB.NET:
If m_SomeForm IsNot Nothing Then
or
VB.NET:
If m_SomeForm Is Nothing Then
 
The problem occurs outside the Called Class; as part of the caller, not a part of the class itself. It's a matter of opening and reopening the form multiple times.

ClassA calls ClassB with .Show() and maintains the reference.

ClassA after the reference has been collapsed (Disposed) cannot define ClassB because it's in Disposed mode and the "Handle/Pointer" is broken because there is no data related, so it is a state problem, and shows that .NET is also in error about being stateless code, which it promotes in the webside development. So to clear the state, you have to run a garbage collection to clear the managed array information.

What MicroSoft ought to do is manage the list with the IsDisposed flag and when it's set to true; run an automatic removal from the list or collection immediately. It's an error in logic despite what the .NET guys tell you. It is incomplete logic.

Something like : ' Clean coding not that complicated jazz



VB.NET:
Private lastStartIndex as Integer = 0

Public Sub WhileDisposing(startIndex as Integer, optional indexWorkLength as Integer = 10) 
    Dim countRowOffset as Integer = 0
    Dim localCopyArray as Array = Nothing
    Dim removeIndexes() as Integer = Nothing

    If Not WhateverTheManagedIndexArrayIs Is Nothing Then

       localCopyArray = WhateverTheManagedIndexArrayIs.Clone()

       For x = startIndex to startIndex + indexWorkLength
          If x < localCopyArray.length Then
             If WhateverTheManagedIndexArrayIs(x).IsDisposed Then
                AddToArray(removeIndexes, x)
             End If
          End If
       Next

       If Not removeIndexes Is Nothing Then countRowOffset = removeIndexes.Length 
       For x = 0 to removeIndexes.Length
                RemoveThisIndexFromArray(WhateverTheManagedIndexArrayIs, removeIndexes(x))
       Next

      lastStartIndex = startIndex + indexWorkLength - countRowOffset 
   End If
End Sub

Force WhileDisposing state as a part of disposing. Very simple very clean and guarenteed.

It's a managed resources issue; because they want to keep variables in scope rather then declaring them new each time; so all of a sudden they have overhead because they created the overhead in the sense of wanting to know what variables are where and what they are/were doing.
 
Last edited:
Microsoft ought not to do anything. Things are fine as they are. You're just trying to turn something that's very simple into something that's very difficult. The only time I've ever needed to use the IsDisposed property is if I want singleton-style behaviour from a form. It's very, very simple: if you call Show on a form and then call Close, the form is disposed, i.e. its handle is released. The one and only reason you would need to test IsDisposed on a form is if you want to call Show on it and you're not sure if Close has already been called. In that case, the code is very, very simple:
VB.NET:
If myForm Is Nothing OrElse myForm.IsDisposed Then
    myForm = New SomeForm
End If

myForm.Show()
myForm.Activate()
That is all you need, so why make a big song and dance about it? That code will focus an existing form if there is one or create and display a new one if there isn't. Simple; logical; easy.
 
Thats what I thought too.

I received the error in a non - singleton state; it was being used in a conventional way in the form of a usercontrol calling the "form.show" method it was allowed for multiple form opens I had no restrictions.

The reason the error occured is because of how I handle back processes during the idle state; it's a tweek to maximize performance in coding. Instead of using forced user button controls for everything I setup a handler in the background that runs during an idle phase of the application; this does basic background work such as repaints, and updates to form variables and such; so therefore object states become an issue, and I manage the states of the objects.

Its a superior way of doing development and usually replaces your "For" and "Do while" loops because it's easier to control the application levels according to the user need. This is what the "real programmers and software engineers" do to make very large applications with lots of data be useful instead of waiting for 3 hrs for the application form to load so that customers are happy with performance over time.

Anyway. As a result this error occurs in a form of stepping on the object while it's attempting to dispose; instead of the object just disposing. I don't understand why there is a need for a IsDisposing property at all. Why isn't it just gone as I said it's not like I can "UnDispose" the object. This is not a valid state of an object. What does Microsoft consider everything a flag variable and you just "flag" something to be comitted or deleted?

If that was the case then timing functions will be out of the picture, because there is no "real-time" updating; so it gets down to the nitty gritty of handling the object state; is it predictable; and thats what the engineers do. Predict states and handle them.

How do you ask an object that is supposed to be nullified if it exists? THE WHOLE PREMISE MAKES NO SENSE.

In simple english that is like asking an orange that isn't there if it's been eaten.

So yes, I am very sorry if you don't like the statement, but Microsoft really needs to rethink this because it's another ERROR in their logic and no worries we all do it; so they need the feedback to see it from the logical point of view that is different then their "elitist" view of the universe.

Believe you me, I know I've been coding for 22 years and been working on Microsoft Platforms for years; they do the same things over and over again. Their major issue isn't that the product isn't good; it's that they aren't paying attention to details; and something like "IsDisposing" can easily be exploited to cause avoidable application and system failures.

The real engineers have to worry about stuff like; if I have 30 million dollars worth of product going through this thing and then suddenly some hacker does an IsDisposed query look up that somehow fails the application and I lose a 10 million dollar transaction CAN I RECOVER IT?

So please, less ego, and take what I say as a constructive critique.
 
There is no IsDisposing property. There's an IsDisposed property. In the case of a control, the IsDisposed property tells you specifically whether the object has released its Window handle back to the OS or not. It says NOTHING about whether or not the object still exists. As with all managed objects, it exists in memory until the GC chooses to clean it up. In practical terms, the object exists as long as you have a reference to it.

If it was displayed by calling its Show method, a form is disposed when you call its Close method. Why would it cease to exist at that point? Just because you've closed it doesn't mean that you don't want to use it. It just means that you don't want to display it.

I take what you say as being as constructive as it was regarding generic objects. You are trying to force .NET to work the way you think it should. The way forms work with regards to disposal is fine as it is. Other than yourself, I'm not aware of anyone who has an issue with it. It certainly could work another way and that might be just as legitimate, but there's nothing illegitimate about the way it works now. I would suggest that you get a fuller understanding of how something works before suggesting that it should work differently.
 
VB.NET:
If myForm Is Nothing Or Else myForm.IsDisposed Then
    myForm = New SomeForm
End If

myForm.Show()
myForm.Activate()

One of us is not communicating well; because I just read what you said like 10 times to make sure.

There's an IsDisposed property. In the case of a control, the IsDisposed property tells you specifically whether the object has released its Window handle back to the OS or not. It says NOTHING about whether or not the object still exists.

If you look at your code for comparisson; you just said something that is contradictive to what you wrote in code. the ".IsDisposed" property (I mistyped when I said IsDisposing) is asssociated (most likely derived from an inheritable class) therefore it is very specific to asking the "object" if it exists in this case the object should always be set to IsDisposed to "False"; because it was created within the event for the first time in every instance the event "click" is invoked.

It only works repeatedly when I check the "IsDisposed" property. Which should just be a variable lookup, apparently it does underline code that forces current managed stated information; that allows the form to load if it was already loaded once if I did not use the IsDisposed property it would not allow the form to load.

I'm not argueing to argue; I am saying very clearly it is an incorrect placement. I should not have to view an objects property that has just clearly been created; to see if it is disposed; because obviously it wouldn't be; therefore it is a problem with managed code - because the old reference still manages that the old variable is active and disposed; unless I force it to view the new one. The logic is incorrect, and the placement is incorrect in this case and it's a very normal routine case.

Instead the old reference is no longer valid in this case; the object has been rendered mute because the event "click" exited and so the local variable is no longer in scope.

When I initiate a new "click" event; it should reinitalize the variable to the new form declaration and this is EXACTLY what it DOES NOT DO. How is the localized variable still in scope after the function is executed? I know your not saying that there is no special handling between local and global variables. The variable IS NEW; so my questions which is stll relevant is why do I have to check the IsDisposed of an object that obviously isn't? and why IsDisposed visible at application level when you'll never view it? It makes no sense; only at System Levels and that is beyond the scope of a simple "Click" event and my initial statement so consider it a subtle pointing of another problem.

The first question I want answered because that is illogical.
 
As I've never seen or heard of a form that has just been created reporting itself as being disposed, I can only assume that the issue lies somewhere in your code. Without seeing more of that code and/or a more detailed explanation of what it does and why, I couldn't confirm or deny that. From what you've shown, there's no reason that that code should behave as you've described. If it was some fault with managed code then everyone would see the same issue. Either you're doing something very out of the ordinary or there is something specifically wrong with your system.
 
Just had a search for the error message and saw some posts on the subject. Didn't read them in detail but I did see at least one post recommend checking IsDisposed and returning. I think each case would be caused by some low-level interaction specific to that case. Hard to say what that might be without more detail on each case.
 
I just open .NET Reflector to get a better understanding of how certain things work. The Control class has a Private Integer field named 'state', whose bits are flags indicating the object's state. One of those bits indicates whether the object is disposed or not. The IsDisposed property merely reports the value of that flag.

The CreateHandle method also checks the value of that flag and throws an ObjectDisposedException if it's set. CreateHandle will be called when you call Show, because the form requires a handle in order to be displayed on screen. I can only assume that something in your code is causing CreateHandle to be called twice, with a call to Close or Dispose in between. We'd need to see the exception stack trace and/or the code involved to diagnose the specific issue.
 
I prerequisit in the begining of the thread that I do back process in an Application.Idle loop; which handles repaints and form updates a very elegant way of handling overhead.

The problem does not occur because of the idle loop; I checked. It happens at the event level when I click to open the form, after I have closed it one time.

Without the .IsDisposed check, the application fails and reports the "Cannot access Disposed Object." error.

With the .IsDisposed check, the application does not fail and works normal.

I think the detail is sufficent in describing the problem.




Without knowing the .NET Framework code; I am assuming that the managed code for .NET is keeping flag identifiers open for "object states" and then sets flags to indicate that an object needs to be removed from an array. Which I eluded to earlier.


This is an issue at application level development, because it's a logic flaw in application development. At application level, the program is expecting the "pointer/handle" to be created real time. When the user hit's "click" it should work. That is not a debate; it just is.



IF I am close in describing the process without knowing the .NET code below; I am probably correct. Because I don't know the .NET framework code and I didn't peer into it; this is all a matter of observation and my personal experience. My best guess is....

At a managed resource level, the manager is expecting historical references; so if I close a form and it disposes, the handle/pointer are referenced for disposal; but when I go to recreate the same variable declaration it steps on the manager and understandably the managed resource takes priority I am assuming the lookup for the variable is by name rather then by a calculated function which it should be ot it's a calculated address space name (if not I have no idea what it is).

If that is true, from an application level this is incorrect - an exploit is open for timing hacks; and it's a matter of opening and closing forms in a timed function which will cause an application to fail; because the search process takes time and if it's search by For / Do While loop; oh boy your really in trouble, and if that is the case then the manager is REALLY messed up because users open and close windows all the time in various timed sequences.

Since there is no reason a variable (localized) cannot be used repeatedly to open 100 instances of the same form; I do not believe the issue is a loop problem. I also do not believe it's a timing issue. Because if it were, I could just wait it out. Which I tried.

I seriously and with all due respect think it's a logical ordering problem.

You cannot effectively manage a real-time state of 100 sub forms by letting the Resource Manager oversea the reference creation; because then the resource manager will be the "boss" of allocating and the timing order (when it gets around to it phylosophy). I think the inverse is more true; because at an application level; the application doesn't care what the resources are; and practically nor does the user all they care about is that it works.

You can manage better if the application is reporting the creation because it goes into queueing theory mathematics; and it will "eventually" make the list and dispose even though it's a timed function it may be late to report but who cares. The only time I think this can be an issue is IF .NET is blocking off ranges and issueing them according to availablity. If thats the case, I know a really cool way of hacking Windows 7 then because thats just dumb the telecommunications companies learned the hardway with black boxes and clear boxes not to do that. Next Available blocks are bad because they are usually out of order, and not easily calculated hard to manage, but easily identified (government phylosophy which never works).

I don't think Microsoft would be that dumb, rather I suspect they would do something more along the lines of next available through searching for available blocks (with guarentee transactions) for QoS by encoding the physical address as an ID value; and calculating the address result of the next variable. Then you end up with fragmentation and I think that is the issue; two objects are open; sharing the same "variable space address (calculated not quantified/tested)" and one is disposed while the other isn't... A Managed Resource problem...

In short; VariableA is reused/recycled and allocated the same spot with the old bitwise flags.

Rather then ...

Instead, of useing a Sin/Cos/Tan wave function and do a gaussian area according to your range; use log of (x (tracking a count)) and get it over with; that way you can optimize according to the usage, and have variable lengths and junking video games will run better.

VariableA is not VariableA; but rather what VariableA was at the next avaialble spot (in proximity) and reflects history (because the time/data can be calculated according to the placement and function index). It reports late; but who cares; not like its doing real-time reporting anyway with managed threads.



If none of that is true; I am WAY off base and don't know what is going on. But, I think I am within an acceptable range of the target.

Sorry lots of words; but I think like a hacker - in small increments - it always works better anyway for identifing root problems.
 
Back
Top