Форма утилизируется случайным образом - PullRequest
0 голосов
/ 29 декабря 2010
Protected 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

Я могу выполнить это 100 раз при тех же самых условиях, и кажется, что 40 раз он потерпит крах со следующей ошибкой:

"Невозможно получить доступ к удаленному объекту. Имя объекта: 'frmImportExport'. "

Он либо умрет на

'within StartProcess()
    Dim __Delegate As New _Delegate(AddressOf StartProcess)
    Me.Invoke(__Delegate)

или

Dim D As New _Delegate(AddressOf SOPERATION)

Я знаю, что трудно ответить, не видя весь код, но я не могу понять, почему это иногда работает, а иногда не работает в одинаковых условиях. Любые идеи о том, что я мог бы искать? Форум не размещается вручную нигде, где я вижу, и этот код выполняется при загрузке формы.


Дополнительная информация:

StackTrace: "в System.Windows.Forms.Control.MarshaledInvoke (Control вызывающая сторона, метод делегата, объект [] args, логическая синхронность) в System.Windows.Forms.Control.Invoke (Делегат метод, Object [] args) в ShiftBilling.BaseForm.StartProcess () в C: \ Users .... \ BaseForm.vb: линия 138 в ShiftBilling.frmImportExport.LoadForm () в C: \ Users \ Alec \ Work \ Levelset \ ShiftBillingSource \ ShiftBilling_Source \ JLRBilling \ frmImportExport.vb: линия 66 "Строка

Содержимое ShowProcess () не очень важно, но вот код в нем:

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

Он никогда не достигнет EndProcess в случае сбоя, поэтому в коде нет реальной необходимости.

Вот код, который выполняется при нажатии на ссылку для отображения формы:

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

Это подчиненная форма, которая должна отображаться в главной форме.

Также стоит отметить, что это был аутсорсинговый проект, с которым мне приходилось работать только полтора дня.

Ответы [ 4 ]

6 голосов
/ 29 декабря 2010
_frmimport.Show()
_frmimport.MdiParent = Me

Это может быть частью вашей проблемы.Метод Show () принудительно создает окно Windows, свойство Handle получает значение.Затем вы изменяете свойство MdiParent, для которого требуется совсем другое окно, дочерний объект MDI.Для чего требуется Winforms, чтобы уничтожить окно Windows и воссоздать его.Значение дескриптора изменяется.Тем временем вы создали поток, в котором используются члены InvokeRequired и Invoke формы.Которые требуют, чтобы свойство Handle было действительным.Это вопрос времени, будь то удар или нет.

Поменяйте местами два утверждения.

1 голос
/ 29 декабря 2010

Будет гораздо легче ответить, если вы разместите дополнительную информацию. В частности:

  1. Трассировка стека полученного исключения.
  2. Больше кода вашего Form класса, особенно методов StartProcess и EndProcess.
  3. Как вы показываете свой Form? Вы используете Application.Run или Form.ShowDialog?

Редактировать

Вот идея:

Переопределите Dispose на вашем Form, и в нем сделайте что-то вроде Debugger.Break();. Теперь снова запустите приложение 100 раз, пока не выясните, почему утилизируется Form. Отправьте trcce стека, показывающий вызов Dispose.

Редактировать 2

Было бы проще понять, если бы вы сказали, что закрываете окно вручную, когда возникает проблема ...:)

Во всяком случае, это поведение является намеренным. В .NET, когда Form создается с использованием Form.Show, когда Form закрывается, Dispose вызывается автоматически.

Но это не должно быть проблемой для вас. Вам не нужно маршалировать вызов StartProcess в поток пользовательского интерфейса, потому что вы alread в потоке пользовательского интерфейса.

И если вы делаете по какой-то причине хотите маршалировать StartProcess из фонового потока в поток пользовательского интерфейса, просто вызовите Invoke в главном окне вместо экземпляра FrmImportExport, который может быть закрытым.

0 голосов
/ 29 декабря 2010

Ошибка «Не удается получить доступ к удаленному объекту. Имя объекта: 'frmImportExport'."означает, что GC собрал frmImportExport, он не был доступен.Из вашего кода видно, что вы храните его в _frmimport, но где он хранится, не показано.Возможно, его хранят во временном местоположении?Создание этой переменной может помочь.

0 голосов
/ 29 декабря 2010

Судя по предоставленной информации, ваша LoadForm происходит в потоке пользовательского интерфейса. Если это так, почему вы используете Me.Invoke ()? Если вы находитесь в потоке пользовательского интерфейса, он немедленно выполнит StartProcess (). Похоже, вы запускаете StartProcess внутри себя? Что приведет к рекурсии. Что-то не так с кодом, который вы предоставили. Я согласен с другими, нам нужно увидеть дополнительный код.

...