.NET 删除事件处理程序并销毁调用的事件

标签 .net vb.net winforms

在我的应用程序的主窗体上,我有一个事件处理程序,它是从与 UI 不同的线程调用的,因为它是由硬件设备生成的事件。 同步。对于 GUI 线程,当事件被调用时,我执行 Form.BeginInvoke()。 然后该调用将在消息循环中排队。

当用户需要关闭表单时,在关闭之前我删除了事件的处理程序,但似乎仍然可以调用调用的调用。 然后,如果处理事件的例程使用了一些在调用它时不再可用的信息,我可能会遇到问题。

例如:

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()之后,有时我会在以下行中收到对象空错误:

If MyGlobalVar.Field = 0 then

我可以在使用变量之前进行 Null 检查,但由于我有许多其他事件,我想要一个更优雅的解决方案。 如何确保删除处理程序后不会发生 Invoked 调用?

在删除所有处理程序以处理待处理消息之前,我是否应该调用 DoEvents?

最佳答案

您遇到的问题是,如果您关闭该事物并将 MyGlobalVar 设置为 Nothing,即使 OnDeviceEvent 对此进行了检查,当您仍在尝试使用它时,它也可能随时变得什么都没有。为了解决这个问题,您可以在访问 MyGlobalVar 时放置一个 SyncLock

Private MyDevice as SomeDevice()
Private MyGlobalVar as MyVarType
Private SyncLockObject as New Object

Public Sub OnDeviceEvent()

   If InvokeRequired Then
      BeginInvoke(Sub() OnDeviceEvent())
      Return
   End If

   SyncLock SyncLockObject
      If MyGlobalVar IsNot Nothing Then
         If MyGlobalVar.Field = 0 then
          'do something
        End If
      End If
  End SyncLock

End Sub

Public Sub PrepareToCloseForm()

   'removes the handler of the event
   RemoveHandler MyDevice.DeviceEvent, AddressOf OnDeviceEvent

   SyncLock SyncLockObject
      MyGlobalVar = Nothing 
   End SyncLock

End Sub

这样,当 OnDeviceEvent 正在访问 MyGlobalVar 时,您无法将其设置为空,并且当 PrepareToCloseForm 将其设置为 Nothing 时,OnDeviceEvent 无法访问它

关于.NET 删除事件处理程序并销毁调用的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46961976/

相关文章:

c# - 远程关闭后保持管道打开的最佳方法

.net - Visual Studio 分析器 [clr.dll]

.net - 在正则表达式匹配中替换

vb.net - Linq-to-Entities 聚合在外部函数中计算的列

c# - ConfigurationManager 在不同的系统上寻找不同的文件

c# - 检查进度条是否被填满

c# - 在 Windows 窗体中使用 SHA-256 散列文本

c# - 从链中删除代表

.net - .Net Color 结构是否使用 HSB 或 HSL 颜色空间?

c# - 从不同线程 vb.net 更新 BindingList(of T)