计时器可以在后台工作程序中停止,但无法启动

时间:2013-08-31 07:38:57

标签: vb.net multithreading timer

最近,我一直在使用system.form.timer中的UI thread。我已经注意到虽然我可以在后台线程上停止计时器,但我无法启动它,除非我使用BeginInvoke,即使我没有收到cross-threading exception。但是在system.timers.timer上似乎我可以从计时器创建的后台线程中停止并启动它。为什么是这样?允许system.form.timer被停止,但是没有从后台线程启用?这对我来说有点奇怪。

System.Form.Timer代码

不工作

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim BW As BackgroundWorker = New BackgroundWorker
    AddHandler BW.DoWork, AddressOf CheckTimer
    BW.RunWorkerAsync()
End Sub

Private Sub CheckTimer()
    Timer1.Stop()
    Timer1.Start()
    MsgBox("Stopped and Started Timer")
End Sub

WORKS

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim BW As BackgroundWorker = New BackgroundWorker
    AddHandler BW.DoWork, AddressOf CheckTimer
    BW.RunWorkerAsync()
End Sub

Private Sub CheckTimer()
    Timer1.Stop()
    Me.BeginInvoke(New TimerStart(AddressOf TimerStartFunction))
    MsgBox("Stopped and Started Timer")
End Sub

Private Delegate Sub TimerStart()

Private Sub TimerStartFunction()
    Timer1.Start()
End Sub

System.Timers.Timer代码

WORKS

Dim aTimer As System.Timers.Timer

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    aTimer = New System.Timers.Timer(5000)
    AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
    aTimer.Enabled = True
End Sub

Sub OnTimedEvent()
    aTimer.Stop()
    aTimer.Start()
    MsgBox("Stopped and Started Timer")
End Sub

1 个答案:

答案 0 :(得分:5)

Winforms Timer类有些线程安全,不足以让你开心。当您调用其Start()方法时,它会创建一个隐藏窗口,将WM_TIMER消息转换为Tick事件。

当您在工作线程上执行此操作时,您往往会遇到问题,这些WM_TIMER消息仅在线程运行消息循环时调度。工作线程通常不这样做,它们不调用Application.Run()。所以计时器不会打勾。

调用Stop()方法是好的,它知道如何在错误的线程上运行代码时找回隐藏的窗口。您在BeginInvoke()中找到的解决方法可以正常工作,因为它现在可以在UI线程上正确调用Start()并获取使用正确的所有者线程创建的隐藏窗口。 System.Timers.Timer没有这个问题,它不依赖于WM_TIMER来勾选,而是使用System.Threading.Timer。由CLR管理的专用工作线程支持哪一个。请注意,此计时器非常危险。在一个工作线程上调用MsgBox()从根本上说是错误的。用户永远不会看到它的高赔率,因为它将在UI窗口后面。

这解释了,我无法提供更好的建议,因为我无法看到你真正想做的事情。小心,你正在玩火。

相关问题