我遇到这种情况:一个带有System.Timer的表单(AutoReset = False)。表单的主线程和计时器也是自己的线程(这里没什么新东西)。
当用户按下按钮时我需要停止计时器,等到计时器线程停止执行并再做一些事情。
另一方面,计时器更新表单中的项目,以便使用BeginInvoke。代码如下所示:
按钮代码:
Private Sub ButtonStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonStop.Click
SyncLock (m_stopLock)
m_stopProcessTimer = True
Threading.Monitor.Wait(m_stopLock)
End SyncLock
''#Do more things here after the timer has end its execution and is stopped
End Sub
计时器代码:
Private Sub m_processTimer_Elapsed(ByVal sender As Object, ByVal e As System.EventArgs) Handles m_processTimer.Elapsed
Dim auxDelegate As EventHandler
SyncLock (m_stopLock)
If Not m_stopProcessTimer Then
If Me.InvokeRequired Then
auxDelegate = New EventHandler(AddressOf m_processTimer_Elapsed)
Me.BeginInvoke(auxDelegate, New Object() {sender, e})
Else
DoFormStuf()
m_processTimer.Start()
End If
Else
Threading.Monitor.Pulse(m_stopLock)
End If
End SyncLock
End Sub
重点是我等待主线程让计时器线程结束其工作。
问题是当用户在要调用BeginInvoke时单击按钮时,此代码会死锁。怎么这样的简单事情可以做到?看起来我找不到解决这个问题的好方法:(
答案 0 :(得分:2)
根本不要使用锁,只需确保在UI线程上执行所有操作,并且可以保证不会损坏任何内容。请记住,调度程序项在UI线程上运行,因此您知道如果您在调度程序项或事件处理程序中执行所有操作,则只执行一个事项一段时间。
答案 1 :(得分:0)
1)也许更多的代码会有所帮助。你是否创建了一个新线程并将计时器置于该线程上?
2)您是否尝试过使用ManualResetEvent(.WaitOne()和.Set()?)
3)在您的活动中,如果需要调用,您将再次重新调用您的活动。混乱...
4)你应该等到另一个线程完成吗?那么Thread.Join()?