我有 3 个函数:
- wait((:在处理时显示加载表单。
- runwait((:使表单加载在线程中工作。
- 停止等待:在处理完成后停止加载。
问题:函数工作正常,但有时以某些形式显示此错误"在创建窗口句柄之前无法在控件上调用 Invoke 或 BeginInvoke">
Public Sub wait()
ld = New Wform
Application.Run(ld)
End Sub
Public Sub runwait()
Dim th As System.Threading.Thread = New Threading.Thread(AddressOf wait)
th.SetApartmentState(ApartmentState.STA)
th.Start()
End Sub
Public Sub stopwait()
ld.BeginInvoke(New Action(Sub() ld.Dispose()))
End Sub
当然,这些选项之一应该会让您满意
1.这很简单。只需显示表格并处理它。它不是模式的,它在原始 UI 线程上运行。wait
不是阻塞调用,因此不需要任何其他线程。当窗口关闭时,一段时间后自动调用"释放它"。如果您在关闭后尝试处置,则有可能它已经被处置,您将获得您得到的异常。请参阅底部处理这种情况的stopwait
方法。
Public Sub wait()
ld = New Wform()
ld.Show()
End Sub
2.这是阻塞。显示对话框窗口会阻止其他代码运行。 如果要释放,则需要调用stopwait
,因为对话框窗口在关闭时不会自动释放。在表单关闭之前,您无法使用呼叫表单。
Public Sub wait()
ld = New Wform()
ld.ShowDialog()
End Sub
3.当从非 UI 线程调用wait
时。(1. 和2.都可以使用此方法确保 UI 线程安全。当 UI 应用程序中存在多个线程时,通常最好使用 InvokeRequired/Invoke 模式。
Public Sub wait()
If Me.InvokeRequired Then
Me.Invoke(New Action(AddressOf wait))
Else
ld = New Wform()
ld.Show()
End If
End Sub
在大多数情况下,ShowDialog
和Show
应该满足您尝试执行的操作:阻止或不阻止。
在所有情况下,stopwait
看起来都一样。
Public Sub stopwait()
If ld IsNot Nothing Then
If ld.InvokeRequired Then
ld.Invoke(New Action(AddressOf stopwait))
Else
If Not ld.IsDisposed Then ld.Dispose()
End If
End If
End Sub