VB.NET 2010、.NET 4
大家好,
我有一个 System.Timers.Timer 对象,它对其经过的事件做了一些工作:
Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
MasterTimer.Enabled = False
'...work...
MasterTimer.Enabled = True
End Sub
我的问题是它所做的工作有时会卡住。部分工作是串行通信,因此它可能会在等待某物的响应时卡住。我已经稍微修改了我的串行通信代码,希望能解决这个问题。然而,这个计时器基本上是生产控制应用程序的心跳,如果它因任何原因停止是非常糟糕的。我在想设置一个故障安全超时可能会很好,这样,如果“工作”花费的时间太长,计时器可以重新启用自己并重试。我在想这样的事情:
将工作移入子例程并创建委托:
Private Delegate Sub WorkDelegate()
Private Sub Work()
'...work...
End Sub
通过调用委托来调用工作,然后在 IAsyncResult 上使用 WaitOne(timeout) 来指定超时:
Private Sub MasterTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles MasterTimer.Elapsed
MasterTimer.Enabled = False
Dim workDel as New WorkDelegate(AddressOf Work)
Dim result as IAsyncResult = workDel.BeginInvoke
result.AsyncWaitHandle.WaitOne(CInt(MasterTimer.Interval))
MasterTimer.Enabled = True
End Sub
但是,我的问题是:如果 Work() 真的被卡在某个地方,这会导致问题吗?因为它会重新进入一个已经运行的子程序?如果 Work() 在超时后没有完成,有没有办法中止它?换句话说,如果在 WaitOne 之后 result.IsCompleted 为 False,就停止 Work() 的执行?
我不太了解这些东西,所以,任何意见将不胜感激。也许有一种我不知道的完全不同的方法来解决这个问题?
提前非常感谢!
我想补充一点:
虽然我打算按照 Hans 的建议进行一些重写,但我已经安排了一天的测试来尝试隔离这个错误的来源。到目前为止,它仅在运行已编译的应用程序时发生。我今天(和昨天)花了一些时间尝试在调试模式下运行时重现冻结,以便我可以添加一些断点并弄清楚发生了什么。到目前为止,该程序还没有在调试模式下冻结。我只是想知道调试环境是否有任何不同可以解释这一点。可能只是我很“幸运”,但我运行它的时间可能是程序在运行可执行文件时冻结的平均时间的三倍......再次,我很无知,但是调试环境有什么独特之处可以解释这一点吗?如果它冻结,我会再次更新。