在我的应用程序的主窗体上,我有一个事件处理程序,它是由硬件设备生成的,因此从与UI不同的线程调用。
为了与GUI线程同步,在调用事件时,我使用Form.BeginInvoke()。
然后,呼叫排队在消息循环中。
当用户需要关闭窗体时,在关闭之前,我会删除事件的处理程序,但似乎调用的请求仍可能被调用。 如果处理事件的例程使用一些在它被调用时不再可用的信息,我可能会遇到问题。
例如:
在运行 PrepareToCloseForm() 后,有时我会在下面这行代码中遇到对象 Null 错误:
当用户需要关闭窗体时,在关闭之前,我会删除事件的处理程序,但似乎调用的请求仍可能被调用。 如果处理事件的例程使用一些在它被调用时不再可用的信息,我可能会遇到问题。
例如:
Private MyDevice as New SomeDevice()
Private MyGlobalVar as MyVarType
Public Sub OnDeviceEvent()
If InvokeRequired Then
BeginInvoke(Sub() OnDeviceEvent())
Return
End If
If MyGlobalVar.Field = 0 then
'do something
end if
End Sub
Public Sub PrepareToCloseForm()
'removes the handler of the event
RemoveHandler MyDevice.DeviceEvent, AddressOf OnDeviceEvent
MyGlobalVar = Nothing
End Sub
在运行 PrepareToCloseForm() 后,有时我会在下面这行代码中遇到对象 Null 错误:
If MyGlobalVar.Field = 0 then
我可以在使用变量之前进行空值检查,但是由于我有许多其他事件,我希望有一个更优雅的解决方案。如何确保在移除处理程序后不会发生调用?
在删除所有处理程序之前,是否应该调用DoEvents以处理挂起的消息?
Eventhandler
后,它将不再被执行。但是在DeveiceEvent
被触发后、移除处理程序之前并且访问MyGlobalVar
时,可能存在“竞态条件”的情况,因为此时变量已经设置为Nothing
。全局变量的目的是什么?您可以考虑传递值给处理程序,而不是使用全局变量。根据您当前的设计,检查null将是最简单的解决方案 - 您可以引入返回所需值并在该方法中检查null的方法。 - Fabio