Почему копия значения MainForm создается, когда метод вызывается или вызывается в кросс-потоке?

Обновление: я думаю, что это как-то связано с ленивым созданием дескриптора окна для MainForm - но покаЯ не мог понять, как это приведет к поведению, замеченному здесь.

Приложение запрашивает данные через сторонний интерфейс COM, обеспечивая обратный вызов для обработки результатов. В обратном вызове пользовательский интерфейс должен быть обновлен - но обновление нет работает как положено. Это'как если бы была создана копия значения MainForm, когдаMainForm.DataReady вызывается или вызывается напрямую через поток, но обновление пользовательского интерфейса работает, как ожидается, при выполнении из обработчика событий. Вы можете объяснить, почему?

(Заметка:AppDomain.CurrentDomain.Id всегда1 проверено ли в MainForm или в ClassB.)

Исходный код - вызвать DataReady из экземпляра ClassB без логики InvokeRequred / Delegate / Invoke в MainForm. Изменение пользовательского интерфейса приложения работает, как и ожидалось, MainFormSomeListControl.EmptyListMsg = "Not Available" изменение непридерживаться' (как будто применяется к отдельной копии MainForm)



Module AppGlobals
  Public WithEvents A As ClassA
End Module

Partial Friend Class MyApplication
  Private Sub MyApplication_Startup(ByVal sender As Object,
                                          ByVal e As StartupEventArgs) Handles Me.Startup
    A = New ClassA()

  End Sub
End Class

Class MainForm

  private sub getData
    ToggleWait(True)
    SomeListControl.Clear()
    A.getData() 'Sets up the com object & callback
  end sub

  Public Sub DataReady()
    ToggleWait(False)
    ' Do something with the data
  End Sub

  Private Sub ToggleWait(toggle as Boolean)
    Application.UseWaitCursor = False
    if toggle then
      SomeListControl.EmptyListMsg = "Not Available"
    else
      SomeListControl.EmptyListMsg = "Please Wait"
    end if
  End Sub

End Class

Class ClassA

  public sub getData()
     Dim ComObj as New ComObject
     Call ComObj.setClient(New ClassB)
  End Sub

End Class

Class ClassB
  Implements IComObjectClient

  sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback
    ' Get the results
    MainForm.DataReady() 
  end sub

End Class

Добавлена логика InvokeRequred для DataReady, которая по-прежнему вызывается непосредственно из ClassB, InvokeRequired никогда не соответствует действительности, изменение пользовательского интерфейса приложения работает, как и ожидалось, MainFormSomeListControl.EmptyListMsg = "Not Available" изменение непридерживаться' (как будто применяется к отдельной копии MainForm)


  Class MainForm
    Public Delegate Sub DataReadyDelegate(ByVal toggle As Boolean)
    ...
    Public Sub DataReady()
        If InvokeRequired Then
            Invoke(New DataReadyDelegate()
        Else
          ToggleWait(False)
          ' Do something with the data
        End If
    End Sub
    ...
  End Class

ВызванныйMainForm.DataReady прямо из ClassB Получил исключение: "Invoke или BeginInvoke нельзя вызывать для элемента управления, пока не будет создан дескриптор окна. " пока я не заставил создание дескриптора окна. Затем это'такое же поведение, как и раньше, а именно, InvokeRequired никогда не выполняется, изменение пользовательского интерфейса приложения работает, как и ожидалось, MainFormSomeListControl.EmptyListMsg = "Not Available" изменение непридерживаться' (как будто применяется к отдельной копии MainForm)


Class ClassB
  Implements IComObjectClient
  Public Delegate Sub DataReadDelegate()

  sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback
    ' Get the results 
    If Not MainForm.IsHandleCreated Then
      ' This call forces creation of the control's handle
      Dim handle As IntPtr = MainForm.Handle
    End If
    MainForm.Invoke(New DataReadyDelegate(AddressOf MainForm.DataReady))
  end sub

End Class

Выполнено из обработчика событий Определено обычай »получил данные события в ClassA и ClassB. ClassA прослушивает ClassB.got_data_event и вызывает ClassA.got_data_event, MainForm прослушивает ClassA.got_data_event и обрабатывает его, вызывая DataReady (). Это работает - InvokeRequired имеет значение true, Invoke оправдан, интерфейс приложения и интерфейс MainForm работают должным образом.


  Class MainForm
    Public Delegate Sub DataReadyDelegate()
    ...
    Public Sub DataReady()
        If InvokeRequired Then
            Invoke(New DataReadyDelegate()
        Else
          ToggleWait(False)
          ' Do something with the data
        End If
    End Sub

    Public Sub _GotData_HandleEvent(ByVal resultMessage As String)
        DataReady()
    End Sub

    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles Me.Load
        ...
        ToggleWait(False)
        AddHandler A.GotData, AddressOf _GotData_HandleEvent
        ...
    End Sub
    ...
  End Class

Ответы на вопрос(1)

Ваш ответ на вопрос