在Timer.Elapsed事件期间访问表单控件

时间:2015-08-10 17:04:03

标签: wpf vb.net timer

我有一个用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的文字时会发生同样的问题。

1 个答案:

答案 0 :(得分:0)

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