更新:我认为这与 MainForm 的窗口句柄的延迟实例化有关 - 但无法弄清楚这将如何导致此处看到的行为。
应用程序通过第 3 方 COM 接口请求数据,提供回调以处理结果。在回调中,需要更新 UI - 但更新没有按预期工作。就好像 MainForm 的值副本已创建,何时MainForm.DataReady
直接跨线程调用或调用,但 UI 更新在从事件处理程序执行时按预期工作。你能解释一下为什么吗?
(注意:AppDomain.CurrentDomain.Id
总是1
在 MainForm 或 ClassB 中检查。)
初始代码- 从 ClassB 实例调用 DataReady,而 MainForm 中没有 InvokeRequred /Delegate /Invoke 逻辑。应用程序 UI 更改按预期工作,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
向 DataReady 添加了 InvokeRequred 逻辑,仍然直接从 ClassB 调用。InvokeRequired 永远不会为真,应用程序 UI 更改按预期工作,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 永远不会为真,应用程序 UI 更改按预期工作,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 已执行,Application UI 和 MainForm UI 更改按预期工作。
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