请求的行为:我想听听建议的通用解决方案,以暂停调用线程,直到在流/串行端口上接收到特定缓冲区。目前,我不关心超时等问题,但我需要一些健壮的东西。
尝试的方法:
Class myClass
{
private SerialPort _port; //Assume configured and connected.
public void WaitFor(byte[] buffer)
{
int bufferLength = buffer.Length;
byte[] comparisonBuffer = new byte[bufferLength];
while(true)
{
if(_port.BytesToRead >= bufferLength)
{
_port.Read(comparisonBuffer, 0, bufferLength);
if (comparisonBuffer.SequenceEqual(buffer)) { return; }
}
}
}
{
我在这方面取得了相当大的成功,但它只是有一种“hacky”的感觉。它经常给我带来麻烦。我相信这是因为我无法保证在预期数据包之前或之后都没有收到其他数据,所以自然而然地,这种方法最终可能会不同步地读取流。在这种情况下,我不想丢失前导/尾随数据,但该方法应该释放线程。
我需要以程序化的方式实现,因此事件驱动的方法对我来说并不适用。在一般意义上,我希望能够实现为;
Do thing;
WaitFor(mybuffer);
Do other thing;
最佳答案
SerialPort.Read()
已经阻塞,直到至少一个字节到达。因此,您不需要(也不应该)像现在这样使用 BytesToRead
- 您已经引入了一个可怕的忙等待循环。
相反,做这样的事情:
// Reads 'count' bytes from a serial port into the specified
// part of a buffer. This blocks until all the bytes have been read.
public void BlockingRead(SerialPort port, byte[] buffer, int offset, int count)
{
while (count > 0)
{
// SerialPort.Read() blocks until at least one byte has been read, or SerialPort.ReadTimeout milliseconds
// have elapsed. If a timeout occurs a TimeoutException will be thrown.
// Because SerialPort.Read() blocks until some data is available this is not a busy loop,
// and we do NOT need to issue any calls to Thread.Sleep().
int bytesRead = port.Read(buffer, offset, count);
offset += bytesRead;
count -= bytesRead;
}
}
以下是根据 BlockingRead()
实现原始代码的方式:
public void WaitFor(SerialPort port, byte[] buffer)
{
byte[] comparisonBuffer = new byte[buffer.Length];
while (true)
{
BlockingRead(port, comparisonBuffer, 0, comparisonBuffer.Length);
if (comparisonBuffer.SequenceEqual(buffer))
return;
}
}
关于c# - WaitFor() - 如何等待特定缓冲区到达 Steam/SerialPort?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39329448/