Jer WasHere
Jer WasHere

Reputation: 33

form.Invoke(delegate) Cannot access a disposed object. .net

Enviroment: vb.net visual studio 10 - win forms

The Error:

{"Cannot access a disposed object. Object name:'frmInfo'."}

StackTrace:

at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) at HorizonRealTime.UI.frmInfo.UpdateGUI(cHorizonColoredString strdata) in R:\csavb2010dlls\Test\TestSoloutions\StoreAutoStuff\HorizonRealTimeVB10\CommanderRealTime.UI\frmInfo.vb:line 93 at HorizonRealTime.UI.frmInfo.DoWork() in R:\csavb2010dlls\Test\TestSoloutions\StoreAutoStuff\HorizonRealTimeVB10\CommanderRealTime.UI\frmInfo.vb:line 75 at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

Simple Explanation:

I have 1 main form with many child mdi forms.

One form(frminfo) manages all the status/error messages that server processes generate.

These messages get placed on a

Imports System.Collections.Concurrent
Public oStatusMsgs As BlockingCollection(Of String) = New BlockingCollection(Of String) 'thread safe collection

The problem occurs very rarely(usually just on application startup) when it enters the if me.invokerequired { me.Invoke(delegate)} I get a object disposed error when it tries to invoke itself.

even in debug the object is not flagged as disposed after the error occurs.

if I wrap the me.invoke in a try/catch... it procedes to process the following messages just fine.

Output in textbox ends up looking like this:

---Refreshing Data---
#Items Data Refreshed#
#Deps Data Refreshed#
Real-Time Info - Error Displaying GUI Info - #Units Data Refreshed# -    Cannot access a disposed object. Object name: 'frmInfo'.
#Retail Data Refreshed#
#Tax Data Refreshed#
---Exiting Data Refresh---

Whats funny is that this textbox is on frminfo that im copying the text out of.

Whats even stranger is. It is actually processing messages prior to getting this error. So the disposed error exception seems to be a false reading, and something else is actually occurring.

On frminfo is a low-priority thread that loops infinitely basically like this

Private sub DoStuff()     'this is kicked off from the frminfo.onload event as a new thread that is referenced by frminfo
    dim strdata as string = nothing
    do while active
        If Me.frmparent.oStatusMsgs.Count > 0 Then
            Me.frmparent.oStatusMsgs.TryTake(strdata, 300)
            If Not strdata Is Nothing Then
                Call me.UpdateGUI(strdata)
            End If

            strdata = Nothing
        End If
        thread.sleep(50)
    loop        
End sub

Private Sub UpdateGUI(ByVal strdata As string)
    If Me.InvokeRequired Then
        Try
            Me.Invoke(New UpdateGUIDelegate(AddressOf UpdateGUI), New Object() {strdata})
        Catch ex As Exception
            Me.frmparent.oErrorMsgs.Add(Me.Text & " - Error Displaying GUI Info - " & strdata & " - " & ex.Message)
        End Try
    Else
        'this is where it would append the strdata to some kind of textbox or other form level control
    end if
end sub

On the main UI thread I do create addition references to this mdi child form.

The first is a collection I add every mdi child form to. I let the GC handle this entirely other then the add.(I do this to ensure my forms are not disposed of)

There is also a collection of forms that I use to sort the mdi childs. The

in some cases i do like

dim otmpinfofrm as form = frmcollection(i)
frmcollection(i) = nothing   'where this is where frminfo currently resides in the collection
frmcollection(i) = frmcollection(i+1)

I loop through the collection and at the end i put back in the reference to

frmcollection(lastindex) = otmpinfofrm

I dont think this sorting could impact the thread calling me.invoke to update a local control. Since Im just sorting references?

Any help would be appreciated regarding better use of the me.invoke to avoid this error from happening at all.

Upvotes: 0

Views: 482

Answers (0)

Related Questions