VB.NET 2010,.NET 4

大家好,

我有一个系统。

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(超时)来指定超时:

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

但是,我的问题是:如果工作()真的被困在某个地方,这会导致问题吗?因为它将重新进入已经运行的子例程?如果超时后没有完成工作,是否有办法中止工作()?换句话说,只需停止执行工作()如果结果。

我真的不太了解这些东西,因此,任何评论都将不胜感激。也许有一种完全不同的方法来解决这个问题?

非常感谢!

我想添加一些东西:

尽管我打算按照汉斯的建议进行一些重写,但我已经安排了一天的测试来尝试隔离此错误的源头。到目前为止,它仅在运行编译应用程序时才发生。我今天(以及昨天)试图在调试模式下跑步时尝试复制冻结,以便我可以添加一些断点并弄清楚发生了什么。到目前为止,该程序尚未在调试模式下冻结。我只是想知道调试环境是否有什么不同的可能解释这一点。可能只是我很“幸运”,但是我经营的可能是平均时间长度的三倍,然后该程序在运行可执行文件时冻结...再次,我很无知,但是有什么东西关于可以解释这一点的调试环境的独特之处?如果冻结,我将再次更新。

有帮助吗?

解决方案

在代码的第一行中,这是错误的。 system.timers.timer类很奇怪,绝对不能保证呼叫stop()会阻止其他呼叫。计时器使用threadpool.queueuserworkitem来进行经过的事件处理程序调用。如果ThreadPool忙碌,这可能最终会排队几个电话,等待从TP调度程序开始运行。停止计时器并不能阻止那些等待线程运行。没有使用锁,这些线程将互相严重踩踏,并弄乱您的通信状态。

一个安全的是system.threading.timer,其周期为零,因此您只会得到一个回调。用更改()方法为计时器充电。

调用代表的begininvoke()方法,然后阻止其完成,这是没有意义的。只需调用Invoke()。使您免于燃烧另一个线程。

是的,如果“工作”方法永远不会返回,那么您有问题。一个无法解决的。

如果您避免使用投票来查看串行端口上是否有任何可用的东西,那么许多苦难可能会消失。让它告诉你,有一些值得的事情。只要接收缓冲区中至少有一个字节,它就会在线程池线程上提高数据序列事件。使用其WriteTimeOut属性也是避免在通信协议或设备不对劲时陷入困境的绝佳方法。专用一个线程并进行阻止读取通话也很好。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top