【问题标题】:Accessing form controls during Timer.Elapsed event [duplicate]在 Timer.Elapsed 事件期间访问表单控件 [重复]
【发布时间】:2015-08-11 04:20:52
【问题描述】:

我有一个用 VB.net 编写的 WPF 应用程序。我试图在计时器事件期间访问表单控件,但代码抛出异常。以下是我的代码:

Public WithEvents attendanceFetchTimer As System.Timers.Timer

Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
    attendanceFetchTimer = New System.Timers.Timer(cfgAttFetchInterval)
    AddHandler attendanceFetchTimer.Elapsed, New ElapsedEventHandler(AddressOf getAllDeviceAttendance)
    attendanceFetchTimer.Enabled = True
End Sub

Private Sub getAllDeviceAttendance(ByVal sender As Object, ByVal e As ElapsedEventArgs) Handles attendanceFetchTimer.Elapsed
    If(checkBox1.isChecked) Then 
        'Do something here change the textbox value
        txtStatus1.Text = "Getting Attendance Data Done!"
    End If

End Sub

问题是当我调试时,checkBox1.isChecked 显示此消息:

“无法计算表达式,因为我们停在了无法进行垃圾回收的地方,可能是因为当前方法的代码可能被优化了。”

并在控制台中显示此错误消息:

“WindowsBase.dll 中出现了‘System.InvalidOperationException’类型的第一次机会异常”

当我尝试更改txtStatus1 的文本时,也会出现同样的问题。

【问题讨论】:

  • System.Timers.Timer 是一个非常有毒的类,只有在您完全了解它的作用时才使用它。而且您所做的不合法,您无法在 Elapsed 事件处理程序中访问 UI 组件。请改用 DispatcherTimer。
  • 我已将您的问题作为副本关闭。请参阅我在链接问题中的回答,以了解如何在多线程场景中使用 DataBinding 正确使用 WPF。如果链接的答案不能满足您的需求,请随时发布新问题。

标签: wpf vb.net timer


【解决方案1】:

System.InvalidOperationException 看起来像是由对 UI 组件的跨线程访问引起的。 System.Timers.Timer 默认情况下会在线程池线程上触发 Elapsed 事件。使用 DispatcherTimerTick 事件将在正确的线程上获取内容,以便在 WPF 中访问 UI。

看起来你可能有重复的事件处理程序,因为你有WithEvents/HandlesAddHandler,但我不完全确定它在 WPF 中是如何工作的。您可能想要(未经测试):

Private attendanceFetchTimer As System.Windows.Threading.DispatcherTimer

Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
    attendanceFetchTimer = New System.Windows.Threading.DispatcherTimer()
    AddHandler attendanceFetchTimer.Tick, AddressOf getAllDeviceAttendance
    attendanceFetchTimer.Interval = TimeSpan.FromMilliseconds(cfgAttFetchInterval)
    attendanceFetchTimer.Start()
End Sub

Private Sub getAllDeviceAttendance(ByVal sender As Object, ByVal e As EventArgs)
    If(checkBox1.isChecked) Then 
        'Do something here change the textbox value
        txtStatus1.Text = "Getting Attendance Data Done!"
    End If
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    相关资源
    最近更新 更多