【问题标题】:Are there any .NET replacement for timeBeginPeriod and timeEndPeriod methods?是否有任何 .NET 替代 timeBeginPeriod 和 timeEndPeriod 方法?
【发布时间】:2012-11-05 14:44:33
【问题描述】:

我一直在开发一个在 SerialPort 上进行通信的程序,但遇到了问题。它的通信率低于 50% 或更少。如果没有,它大部分时间都会超时。

根据我对这个问题的研究,我发现默认情况下全局或系统计时器分辨率至少为 10 毫秒或更大。

Serial Communication (RTS) and Windows 7

因此,如果您在通信中使用 Thread.Sleep 暂停 X 毫秒,那么它可以做的最好的事情是 10 毫秒或更长的无操作或暂停。

就我而言,这对于我的程序与外部设备通信来说太长了。设备收到我的程序的请求后会在 10 毫秒内回复。如果我的程序还没有准备好接收回复,那么我的程序将超时。

解决此问题的唯一方法是调整或更改系统计时器分辨率。为此,我被告知使用来自 winmm.dll 的 Windows 方法 timeBeginPeriod 和 timeEndPeriod。虽然我可以为我的 Windows .NET 版本的程序导入这些方法,但我想知道在 .NET 框架中是否有这些方法的替代品。

【问题讨论】:

  • SerialPort 的 DataReceived 事件的响应与定时器分辨率无关。它使用可等待事件,当驱动程序发出“数据接收”事件时,该事件会导致线程上下文切换。期望保证 10 毫秒的响应在 Windows 上是一个失败的原因,它不是一个实时操作系统。需要驱动程序。
  • @HansPassant,不。这与 DataReceived 无关。我也试过了,它本身给我带来的悲伤比解决我的问题更多。因此,我创建了一个用于通过串行端口进行写入和读取的线程。确切地知道设备需要多长时间才能回复,我暂时停下来让我的软件切换 LINE (RTS) 进行读取。一旦读取它就会切换行(rts)进行写入。它只需要 2 或 3 毫秒。所以,我使用thread.sleep。如上所述,thread.sleep(1) 将等待 10 毫秒或更长时间。汉斯,它可能会丢失,但在 3 周的头痛之后,到目前为止我的沟通已经 100% 稳固
  • 这没什么意义。为什么要睡觉?直接调用 Read() 不用any sleep,它只在收到东西时返回。
  • @HansPassant,需要驱动程序??? Visual Studio 2010 自带的还不够吗?我没有安装任何特别的东西。我正在使用 Visual Studio 2010 附带的框架工具 SerialPort。经过几次设置后,我就可以进行通信了。它可能正在使用通用驱动程序。
  • 在我看来,您在从串行端口读取数据时犯了一个非常经典的错误。您忽略了 SerialPort.Read() 调用的返回值。它不是是您要求的字节数。是的,调用 Sleep() 是一种创可贴,它会延迟您的程序足够长的时间以允许驱动程序接收足够的字节。然而,这不是正确的解决方法,您应该继续调用 Read() 直到获得整个设备响应。

标签: .net serial-port delphi-prism oxygene winmm


【解决方案1】:

如果您的目标是避免调用特定于平台的 DLL 函数而只使用 .Net 框架,那么对于短暂的超时,使用 System.Diagnostics.Stopwatch 循环可能是您的最佳选择。

秒表会在出现时自动使用高分辨率计时器。

public static void Pause(long ms) 
{
    Stopwatch t = new Stopwatch();
    t.Start();
    while(t.ElapsedMilliseconds < ms) { }
    t.Stop();
}

这将在暂停循环中阻塞您的调用线程并占用 CPU,以减轻其中一些问题(如果您使用的是多核系统,您可以设置您的进程或线程与另一个核心的关联。How Can I Set Processor Affinity in .NET?

【讨论】:

  • 您也可以考虑在循环中添加Thread.SpinWait(n)
猜你喜欢
  • 2021-11-06
  • 2011-04-21
  • 2011-01-20
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多