Sleep()是一个糟糕的设计,但似乎是我唯一的选择



我正在编写一个IO类,通过RS-232串行将文件上传/下载到控制器。不幸的是,我不能一次发送整个文件,我必须将其分解成数据包,每次发送一点。这是基本的方法……

ifstream file ("path/to/file.ext", ios::in | ios::binary);
while( !file.eof() )
{
    //... zero buffer, and add packet header (8 bytes)
    size_t nResult = file.read( &buffer[8], 129 );
    Serial.Write( buffer, nResult+8 );
    //... see if controller wrote anything to the serial port and process it's command
    Sleep( 600 );
}

我知道使用Sleep()不是一个很好的设计实践,但是如果我删除Sleep()语句,甚至缩短循环睡眠的时间,那么控制器就会抛出关于它的缓冲区已满的错误,并且传输失败。有更好的方法来做到这一点吗?

在你说之前,不,我不能向控制器发送消息来确定它是否准备好接受下一个数据包。它没有这个功能。

编辑:

我忘了提一下,我不得不睡觉的间隔时间有点"盲目"。制造商提供的协议规范没有详细说明数据包之间所需的任何时间长度。所以我必须通过试错法来确定这个值。我担心它可能无法在每台PC上运行,因此它可能无法在每台控制器上运行。

这个开发是为Windows XP/Vista/7做的。

编辑# 2:此外,每个数据包的数据量实际上也是一个试错猜测。协议规范允许65,535字节的数据包(包括报头)。但如果一次发送超过129字节,就会出现问题,有时有效,有时无效。你必须睡觉的时间和你可以发送的字节数之间似乎也有关系。如果我将数据包大小降低到每个数据包20字节,我可以将睡眠时间降低到400毫秒。我认为这些问题的原因源于控制器将数据从缓冲区移动到文件所花费的时间。

您所做的称为盲循环同步。这并不一定是糟糕的设计。如果你的设备没有指示是否准备好接收更多数据的功能,这是唯一的方法。

设备通常会指定最大数据速率或最小字节间隔时间。

我认为这种做法是不好的,因为如果你盲目地选择一个延迟值(如果它比需要的要大,性能会受到影响),如果你有更好的同步方法可用,或者如果你正在使用延迟来掩盖时间问题(比如,在多线程应用程序中)。

另一个不适合使用Sleep的原因是您可能希望该功能尽早退出。如果你选择

WaitForSingleObject(hTerminatingEvent, 600);

您可以让另一个线程通知您想要退出并提前终止的事件。(在这种情况下,即使事件没有发出信号,这个函数调用也会在600毫秒后继续。)

在Windows上,我会使用一个可等待定时器来代替Sleep(),但是如果你的硬件需要延迟,那么你将需要延迟

相关内容

最新更新