好的,这是问题(这与我以前的帖子有关)
我需要能够为串行通信提供问题/响应系统,其工作原理如下:
问题:你好 回应:世界? 问题:不,你好,护士 回应:你没有乐趣。这就意味着我说“你好”远程单位有望发回“世界”?在一段时间内,如果不是,我应该有办法访问该缓冲区,所以这就是我的想法,请给我反馈
ReaderWriterLock'd'readBuffer' 一个将写入流的问题方法 一个响应方法,它将监视readBuffer,直到它包含我期望的内容或超时结束。
首先,stackoverflow社区将如何设计此类,第二,他们将如何编写已识别数据的事件?第三,它们如何使这个代码更加健壮,以便在并行线程中存在多个类的实例以进行同步通信?
答案 0 :(得分:4)
这基本上是一个producer-consumer问题,所以这应该是一般设计的基础。
以下是对此的一些想法:
a)FIFO缓冲区(队列)
首先,您应该为类的每个实例都有一个线程安全的队列实例(FIFO缓冲区)。一个线程将接收数据并填充它,而另一个线程将以线程安全的方式读取数据。这只意味着您必须对每个入队/出队操作使用锁定。
FIFO队列将使您能够同时处理工作线程中的数据,同时从通信线程填充它。如果需要接收大量数据,可以在工作线程中将某些数据出列,并在收到所有数据之前对其进行解析。否则,您需要等到收到所有数据才能一次解析所有数据。在大多数情况下,在您开始解析数据之前,您不知道应该获得多少数据。
b)等待数据的工作线程
我会创建一个工作线程,它会等待收到新数据的信号。您可以使用ManualResetEvent.WaitOne(timeOut)
暂停,以防暂时没有任何问题。收到数据后,您必须根据当前状态对其进行解析 - 这将是state machine的实现。
c)端口抽象
要处理不同类型的端口,你可以将你的串口包装在一个接口中,这可能至少包含这些方法(我可能已经忘记了一些东西):
interface IPort
{
void Open();
void Close();
event EventHandler<DataEventArgs> DataReceived;
void Write(Data data);
}
这有助于您将特定通信代码与状态机分开。
注意:强> (根据Microsoft)不保证每收到一个字节都会引发DataReceived事件。使用BytesToRead属性确定要在缓冲区中读取的数据量。所以你可以创建自己的IPort实现,它会定期轮询SerialPort,以确保你不会错过一个字节(有一个问题已经解决了这个问题)。
d)接收数据
要接收数据,您必须附加IPort.DataReceived
事件的处理程序(或SerialPort.DataReceived
,如果您没有包装它),并将收到的数据排入队列内的队列处理程序。在该处理程序中,您还可以设置提及ManualResetEvent
以通知工作线程已收到新数据。
答案 1 :(得分:0)
我有类似的设计问题,为格式化数据编写异步套接字侦听器。 将我提出的内容翻译成SerialPort / DataReceived模型将是这样的:
主类封装了问题/响应系统 - 它将包含基于输入生成响应的逻辑。该类的每个实例都将绑定到一个可在构造期间或之后设置的串行端口。将有一个StartCommunications类型方法 - 它将DataReceived事件连接到类中的另一个方法。此方法负责从端口获取数据,并确定是否已到达完整消息。如果是这样,它会引发自己的事件(在类上定义),它将有一个适当的方法连接到它。您也可以让它在您的类上调用预定义的方法而不是引发事件 - 我定义了一个事件来提高灵活性。
基本设计在生产系统中运行良好,并且可以处理比连接到它的其余系统更多的输入。