1

在我的 .Net 控制台应用程序中,我使用以下方法将少量字节(大约 20 个)写入串行端口,然后读取响应(同样不超过 20 个字节)。它用于与外部硬件设备通信 - 向其发送数据请求并返回请求的值。

我已经删除了多余的代码、端口初始化、变量声明等,但你仍然可以看到它在做什么:-

var sw = new Stopwatch();
sw.Start();

// Write the "request" bytes.
_port.Write(buffer, 0, buffer.Length);

Console.WriteLine("After write: {0}", sw.ElapsedMilliseconds);
sw.Restart();

// Wait for response, but timeout after 100ms.
var timeoutCount = 0;
while (_port.BytesToRead == 0 && timeoutCount < 100)
{
    Thread.Sleep(1);
    timeoutCount++;
}

Console.WriteLine("Waited: {0}, #loops: {1}", sw.ElapsedMilliseconds, timeoutCount);

if (_port.BytesToRead == 0)
{
    // Timed-out..
    return null;
}

// Read the response.
var receivedData = new byte[_port.BytesToRead];
_port.Read(receivedData, 0, receivedData.Length);

return receivedData;

我的应用程序以紧密(几乎连续)的循环调用上述代码。你会注意到我添加了几个 Console.WriteLines 来输出一些时间,我看到非常一致的数字,如下所示:-

After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
...and so on...

显然,写入发生得非常快,响应也很快到达,因为应用程序只通过while循环一次,尽管我对为什么它只执行一次时显示 14ms 感到困惑Thread.Sleep(1)

更奇怪的是,如果我在 PC 上做其他事情,比如打开另一个窗口,运行 Chrome,或者只是移动鼠标,那么我会看到这样的数字:-

After write: 0
Waited: 4, #loops: 5
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 1, #loops: 2
After write: 0
Waited: 3, #loops: 4

这更像是我对串行端口代码(例如我的)的期望,而不是我在 PC“空闲”时看到的神秘 14 毫秒。关于发生了什么的任何想法?

这给我带来了一个问题,因为我的应用程序需要每 100 毫秒执行大约 12 次写入/读取。您可以从第二组时间(每组几毫秒)中看到,这很容易实现,但是当 PC 处于“空闲”状态时,每次写入/读取需要 14 毫秒,导致我的应用程序经常丢失数据(在外部更新设备每 100 毫秒)。

4

1 回答 1

0

看来您有实时要求,但您正在非实时系统(Windows)上开发。Sleep(1) 只是告诉操作系统你的线程在至少 1ms 内不能被重新激活,所以它会消失至少 1ms,当调度程序到达它时它会回来。

您的鼠标移动似乎使其表现更好的原因是因为它导致调度程序被所有鼠标移动事件更频繁地调用。

考虑使用实时操作系统,或者不依赖窗口进行调度,尽管如果您的 _port.write() 阻塞了诸如 WaitForSingleObject 或 Sleep 之类的系统调用,这可能会很困难。你也可以考虑放弃任何实时要求,只要你得到它就从串行端口得到什么。

于 2012-10-01T11:58:42.297 回答