我有以下情况,
Private Sub MyButton_Click(sender as Object, args as EventArgs) Handles MyButton.Click
Me.pleaseWaitFrm = New PleaseWaitForm()
' Fire up new thread to do some work in (AddressOf DoMyWork)
Me.pleaseWaitFrm.ShowDialog()
End Sub
Private Sub DoMyWork()
Dim log = Me.DoTheActualWork()
Me.pleaseWaitFrm.Close()
Using logFrm as New LogViewer(log)
logFrm.ShowDialog()
End Using
End Sub
如果DoTheActualWork()
来电退出的速度足够快,则会在Me.pleaseWaitFrm.Close()
来电期间发出Me.pleaseWaitFrm.ShowDialog()
来电。结果,毫不奇怪,是这个例外:
System.Windows.Forms.dll中出现未处理的“System.InvalidOperationException”类型异常
附加信息:在执行CreateHandle()时无法调用Value Close()。
显然,这是旧的“你不能。关闭()一个WinForm,而它正在加载”问题。但对我来说不明显的是如何最好地防止这种情况发生?如何安全可靠地延迟.Close(),直到在这种情况下这样做是安全的?
答案 0 :(得分:2)
Me.pleaseWaitFrm.Close()
这是非法通话,您不能从另一个主题关闭表单。不知道你是如何逃避它的,当你使用调试器运行时应该引发IllegalOperationException。检查您的代码并删除对Control.CheckForIllegalCrossThreadCalls属性的任何分配。
你得到的这个例外是一个明显的副作用。您必须使用Control.Invoke()来关闭对话框。这会自动解决您的问题,在加载对话框之前,委托目标无法执行。
利用BackgroundWorker类,它使这很容易。您可以在RunWorkerCompleted事件处理程序中关闭该对话框。
答案 1 :(得分:1)
为什么不设置一个“ShouldClose”标志,可以在关闭表格时安全地检查 - 如果需要可以关闭它?
关于代码示例,我的实现方式略有不同,但请告诉我这是否违反了任何其他要求,我们可以修改它......
''in PleaseWaitForm:
Public Property ShouldClose as boolean = false
Private Sub frmSplash_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Close()
End Sub
''Your posted code
Private Sub MyButton_Click(sender as Object, args as EventArgs) Handles MyButton.Click
Me.pleaseWaitFrm = New PleaseWaitForm()
'' Fire up new thread to do some work in (AddressOf DoMyWork)
Me.pleaseWaitFrm.ShowDialog()
End Sub
Private Sub DoMyWork()
Dim log = Me.DoTheActualWork()
Me.pleaseWaitFrm.ShouldClose = True
If Me.pleaseWaitFrm.Created Then
Me.pleaseWaitFrm.Created.Close
End If
Using logFrm as New LogViewer(log)
logFrm.ShowDialog()
End Using
End Sub
简而言之,如果我们可以关闭表单,我们会这样做 - 否则,设置一个标志,表单将在完成加载时执行。
我在frmSplash.Load()中测试并且没有任何问题调用Me.Close但是如果你遇到任何问题,你可以通过在frmSplash上工作来检查值而不是使用加载事件
修改:发现并修复了错误