Form being disposed of randomly
Pro开发者_JAVA百科tected Overrides Sub LoadForm()
MyBase.LoadForm()
Try
'StartProcess might be causing an error (error msg is issue with loading config, which would be incorrect)
StartProcess()
Dim D As New _Delegate(AddressOf SOPERATION)
Me.Invoke(D)
BusinessObject = New bConfig(Me)
CType(BusinessObject, bConfig).LoadKeyValue()
Catch ex As Exception
MESSAGES.ShowMessage(MessageIndex.ErrInLoadConfigData, TitleIndex.LoadForm, MessageBoxButtons.OK, MessageBoxIcon.Information)
StopProcess()
EnableDisable(CurrentBillType)
End Try
End Sub
I can run this 100 times under the exact same conditions and it seems like 40 times it will crash with the following error:
"Cannot access a disposed object. Object name: 'frmImportExport'."
It will either die on
'within StartProcess()
Dim __Delegate As New _Delegate(AddressOf StartProcess)
Me.Invoke(__Delegate)
or
Dim D As New _Delegate(AddressOf SOPERATION)
I know it's difficult to answer without seeing the entire code, but I cannot for the life of me figure out why this sometimes does and sometimes does not work under the same conditions. Any ideas about what I could look for? The forum isn't being disposed manually anywhere that I see, and this code is being executed on formload.
Additional info:
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 ShiftBilling.BaseForm.StartProcess() in C:\Users....\BaseForm.vb:line 138 at ShiftBilling.frmImportExport.LoadForm() in C:\Users\Alec\Work\Levelset\ShiftBillingSource\ShiftBilling_Source\JLRBilling\frmImportExport.vb:line 66" String
The contents of ShowProcess() aren't really important, but here's the code in it:
Protected Sub StartProcess()
If Me.InvokeRequired Then
Dim __Delegate As New _Delegate(AddressOf StartProcess)
Me.Invoke(__Delegate)
Else
Validator.Clear()
'If Me.MdiParent IsNot Nothing Then
IsProcessRunning = True
frmMain.ShowProgress()
'CType(Me.MdiParent, frmMain).ShowProgress()
EnableControls(False)
'End If
End If
End Sub
It never reaches EndProcess if it fails, so there's no real need for the code.
Here is the code that is executed when the link is clicked to display the form:
Private Sub ImportExportMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ImportExportMenu.Click
_frmimport = New frmImportExport
If clickWindow(_frmimport.Text, _frmimport) = True Then Exit Sub
_frmimport.Show()
_frmimport.MdiParent = Me
SetFormPosition(_frmimport)
End Sub
It's a subform that is to be displayed within a main form.
It may also be worth noting that this was an outsourced project that I've only had a day and a half to work with.
_frmimport.Show()
_frmimport.MdiParent = Me
That could be part of your problem. The Show() method forces the Windows window to be created, the Handle property gets a value. You then change the MdiParent property, which requires an entirely different kind of window, an MDI child. Which requires Winforms to destroy the Windows window and recreate it. The Handle value changes. Meanwhile, you've started a thread that is using the form's InvokeRequired and Invoke members. Which require the Handle property to be valid. It's a matter of timing whether or not that's going to blow.
Swap the two statements.
It will be much easier to answer if you post some more information. In particular:
- The stack trace of the exception you get.
- More code of your
Form
class, especially theStartProcess
andEndProcess
methods. - How are you showing your
Form
? Do you useApplication.Run
orForm.ShowDialog
?
Edit
Here's an idea:
Override Dispose
on your Form
, and in it do something like Debugger.Break();
.
Now run your app again 100 times until you find out why your Form
is being disposed.
Post the stack trrce showing the call to Dispose
.
Edit 2
It would have been easier to figure out if you would say you manually close the window when the problem happens... :)
Anyway, this behavior is by design. In .NET, when a Form
is created using Form.Show
, when the Form
closes, Dispose
is called automatically.
But this should not be a problem for you. You don't really need to marshal the call to StartProcess
to the UI thread, because you are alread on the UI thread.
And if you do for some reason want to marshal StartProcess
from a background thread to the UI thread, simply call Invoke
on the main window instead of on the FrmImportExport
instance that may be closed.
Based on the information provided it seems your LoadForm is occuring on the UI Thread. If this is the case why you are using Me.Invoke()? If you are on the UI thread it will immediately execute StartProcess(). It also looks like you are invoking StartProcess within itself? Which will result in a recursion. Something seems amiss with the code you've provided. I agree with the others we need to see some additional code.
The error "Cannot access a disposed object. Object name: 'frmImportExport'." means that the GC has collected the frmImportExport, it was not reachable. It appears from your code that you're storing it in _frmimport, but where that is stored is not shown. Perhaps its stored in a temporary location? Making that variable shared might help.
精彩评论