【问题标题】:How to handle this Multithread situation and don't lock?如何处理这种多线程情况并且不锁定?
【发布时间】:2009-11-26 02:11:51
【问题描述】:

我有这种情况:一个带有 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 时单击按钮时,此代码会死锁。像这样简单的事情怎么能做到?看起来我找不到解决这个问题的好方法:(

【问题讨论】:

    标签: vb.net multithreading deadlock


    【解决方案1】:

    根本不要使用锁,只要确保在 UI 线程上做所有事情,就可以保证不会损坏任何东西。请记住,调度程序项在 UI 线程上运行,因此您知道如果您在调度程序项或事件处理程序中执行所有操作,那么只有 一个 事情正在执行一次。

    【讨论】:

    • 对不起,我更新了按钮处理程序以显示我需要等待计时器执行结束并停止(它不会再次执行),然后执行一些操作。
    • 不要“等待”,只是让 UI 什么都不做,让 Timer 触发调度程序项来完成其余的工作。无论如何你都不能阻塞在 UI 线程中,否则 UI 会挂起。
    • 好的,现在我明白你的意思了。这是一种从计时器代码中调用的回调,不是吗?
    • 没错,想象一下消息循环的作用会有所帮助:1. 读取调度程序队列,执行所有项目 2. 处理窗口消息 3. 绘制窗口 4. 转到 #1
    【解决方案2】:

    1) 也许多一点代码会有所帮助。您是否创建了一个新线程并将计时器放在该线程上?

    2) 您是否尝试过使用 ManualResetEvent(.WaitOne() 和 .Set() 代替?)

    3) 在您的事件中,如果需要调用,您将再次调用您的事件。令人困惑...

    4) 你应该等到另一个线程完成吗?那么 Thread.Join() 呢?

    【讨论】:

    • 1) 计时器总是在新线程上引发事件。 2) 我认为我将拥有与 ManualResetEvent 相同的锁 3) 据我所知,这是处理需要更新 UI 项的非 UI 线程的正常方法。 4) 不是我创建的线程,是定时器创建的内部线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多