2011-11-23 68 views
7

我正在编写一个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); 
} 

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

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

编辑: 我忘了提,我不得不睡在哪个区间是有点“盲目”。制造商提供的协议规范没有详细说明数据包之间所需的任何时间长度。所以我必须通过反复试验来确定这个价值。我担心它可能无法在每台PC上运行,因此它可能无法在每个控制器上运行。

该开发工作正在为Windows XP/Vista/7完成。

编辑#2: 此外,每个数据包的数据量实际上也是一个试错法猜测。协议规范允许包含65,535字节的数据包(包括头部)。但是,如果您一次发送超过129个字节,您会发现问题有时会起作用,有时不起作用。睡眠时间和可以发送的字节数量之间似乎也有关系。如果我将数据包大小降低到每个数据包20个字节,我可以将睡眠时间降低到400毫秒。我相信造成这些问题的原因是控制器将数据从缓冲区移动到文件的时间。

+0

你总是从控制器得到答案吗? – dwo

+6

如果您的硬件需求包括一次发送如此多的字节,然后等待那么多毫秒,那么实现它的方式并不明显。 – Gabe

+1

是的,我甚至会认为使用睡眠不是一个想法的坏处。我想你可以写一个奇特的函数,包括,但考虑到你的条件,Sleep()听起来很合理。 – ScarletAmaranth

回答

10

你在做什么叫盲循环同步。这不一定是坏设计。如果您的设备没有指示它已准备好接收更多数据的功能,则这是执行此操作的唯一方法。

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

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

+0

有关控制器的更多信息将清除此问题。 – dbasnett

+0

请参阅我的编辑以获取更多信息。 –

2

睡眠可能不正确的另一个原因是您可能希望功能提前退出。如果您改为

WaitForSingleObject(hTerminatingEvent, 600); 

您可以让另一个线程发出要退出并提前终止的事件。 (在这种情况下,即使事件未发出信号,该函数调用仍将在600 ms后继续)。

0

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

相关问题