好吧,在C#中使用这个SerialPort控件,过去4天我一直在苦苦挣扎,没有令人满意的结果。让我解释一下:
我有一个设备(Arduino UNO Board)与ac#prog通信,模拟一个比例(简单的请求/响应模式),设备发送一个由3个字节组成的命令序列(要求称重):CHR(27 )+ P + CHR(13)因此模拟器以模拟重量作出响应(我已经整理了设备如何捕获并解析这个重量,所以这不再是问题所在)。 使用DataReceive事件似乎我正在使用Serialport.Read()丢失数据,所以到目前为止我浪费了这种方法。 模拟器必须始终监听上述序列。字节和必须有一个GUI。我明白为此我必须使用一个线程以防止GUI被锁定(可能是一个后台工作者?)和一种缓冲区,它在(现在)这2个线程之间共享并防止线程同时读/写到缓冲区(我需要状态机吗?)(我请求帮助,因为我不知道这是一个好方法还是我的假设是错误的,或者如果这是一个更容易解决这个问题的方法)所以我我正在寻求建议和(运气不错)代码片段,或者如果你面临开发一个类似的应用程序,你是如何解决它的。
如果需要进一步澄清,我可以提供我迄今为止所做的代码。希望你能对此有所了解。
提前致谢。
更新1
这是我到目前为止的代码:
ConcurrentQueue<byte> queue = new ConcurrentQueue<byte>();
....
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
bool listening = true;
while(listening)
{
if(serialPort.BytesToRead > 0)
{
byte b = (byte)serialPort.ReadByte();
queue.Enqueue(b);
}
}
}
因此,由于命令必须以字符13(ASCII格式的CR)结束:
public string GetCommand()
{
string ret = "";
byte[] ba = new byte[1];
byte b = (byte)' ';
while(b!=13)
{
if(queue.TryDequeue(out b))
{
ba[0] = b;
ret += ASCIIEncoding.ASCII.GetString([ba]);
}
}
return ret;
}
为了测试这个GetCommand()方法,我在buton_click事件中从主ui线程调用它,但它挂起了应用程序,我是否需要创建另一个线程来调用GetCommand()?
答案 0 :(得分:3)
这适用于少量数据。但是如果数据更大,就像传递一些http信息一样,那么队列大小可能还不够。所以我认为你应该使用非阻塞类型的架构。
答案 1 :(得分:1)
请参阅this answer了解如何实施发送方。
对于读取端使用专用线程,在该线程中从端口读取消息,将其排队在合适的并发数据结构(例如ConcurrentQueue)中并立即循环返回以等待下一个输入来自串口。
在单独的线程上使用队列中的输入。
可能有更有效的方法,但这个方法易于实施和万无一失。