正确关闭表单 运行 新线程中的循环
Properly closing a form running a loop in a new thread
我的表单中有方法 运行 在新线程中执行 while 循环。
一旦标记值设置为 true(由另一个处理 Me.FormClosing
的方法设置)
,for 循环就会退出
问题是当表单关闭时,我偶尔会遇到两个异常。
ObjectDisposedException
和 ComponentModel.Win32Exception
.
如何在没有 "eating" 这些异常并忽略它们的情况下正确退出表单。
代码:
Dim _exit As Boolean
Public Sub test()
Dim task As Thread = New Thread(
Sub()
Do
checkInvoke(Sub() a.append("a"))
Loop While _exit = False
End Sub)
End Sub
Private Sub checkInvoke(ByVal _call As Action)
If Me.InvokeRequired Then
Me.Invoke(Sub() checkInvoke(_call))
Else
_call.Invoke()
End If
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
_exit = True
End Sub
我对VB不熟悉,但是我用c++做过类似的事情。主要问题是 for 循环在表单关闭时尚未完成。您可以只隐藏表单,等待线程完成,然后关闭表单。您可以使用标志来标记并行线程的停止。
错误从何而来?
这可能有点令人困惑,但实际上很合乎逻辑...
- 用户(或其他人)关闭了表单。
然后调用 FormClosing
将 _exit
设置为 True
- 然后窗体自行关闭,销毁其句柄。
- 现在,这取决于有时抛出异常的位置:
- 线程刚刚完成调用或循环,检查
_exit
值然后结束循环,一切正常。
- 要么是刚刚开始Invoke,然后调用了一个方法调用UI线程去修改刚刚处理掉的表单上的东西,不再Handle这个表单,导致
ObjectDisposedException
如何预防?
您可以做的一件事是,在您的 FormClosing
事件中,等待线程结束,然后让系统关闭表单:
Private _isFinished As Boolean = False
Private _exit As Boolean = False
Public Sub test()
Dim task As Thread = New Thread(
Sub()
Do
checkInvoke(Sub() a.append("a"))
Loop While _exit = False
'We inform the UI thread we are done
_isFinished = True
End Sub)
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
_exit = True
While Not _isFinished
Application.DoEvent() 'We can't block the UI thread as it will be invoked by our second thread...
End While
End Sub
我的表单中有方法 运行 在新线程中执行 while 循环。
一旦标记值设置为 true(由另一个处理 Me.FormClosing
的方法设置)
问题是当表单关闭时,我偶尔会遇到两个异常。
ObjectDisposedException
和 ComponentModel.Win32Exception
.
如何在没有 "eating" 这些异常并忽略它们的情况下正确退出表单。
代码:
Dim _exit As Boolean
Public Sub test()
Dim task As Thread = New Thread(
Sub()
Do
checkInvoke(Sub() a.append("a"))
Loop While _exit = False
End Sub)
End Sub
Private Sub checkInvoke(ByVal _call As Action)
If Me.InvokeRequired Then
Me.Invoke(Sub() checkInvoke(_call))
Else
_call.Invoke()
End If
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
_exit = True
End Sub
我对VB不熟悉,但是我用c++做过类似的事情。主要问题是 for 循环在表单关闭时尚未完成。您可以只隐藏表单,等待线程完成,然后关闭表单。您可以使用标志来标记并行线程的停止。
错误从何而来?
这可能有点令人困惑,但实际上很合乎逻辑...
- 用户(或其他人)关闭了表单。 然后调用
FormClosing
将_exit
设置为True
- 然后窗体自行关闭,销毁其句柄。
- 现在,这取决于有时抛出异常的位置:
- 线程刚刚完成调用或循环,检查
_exit
值然后结束循环,一切正常。 - 要么是刚刚开始Invoke,然后调用了一个方法调用UI线程去修改刚刚处理掉的表单上的东西,不再Handle这个表单,导致
ObjectDisposedException
- 线程刚刚完成调用或循环,检查
如何预防?
您可以做的一件事是,在您的 FormClosing
事件中,等待线程结束,然后让系统关闭表单:
Private _isFinished As Boolean = False
Private _exit As Boolean = False
Public Sub test()
Dim task As Thread = New Thread(
Sub()
Do
checkInvoke(Sub() a.append("a"))
Loop While _exit = False
'We inform the UI thread we are done
_isFinished = True
End Sub)
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
_exit = True
While Not _isFinished
Application.DoEvent() 'We can't block the UI thread as it will be invoked by our second thread...
End While
End Sub