我正在尝试为C#中的多个单元编写一个串行I/O(RS-232)的测试应用程序,但由于缺乏线程经验,我遇到了一个问题所以我正在招揽对最有名的方法的反馈。
我有一个COM端口COM1-16池,每个端口都可以随时读/写,我需要能够同时管理它们。这是线程池的情况吗?有关构建此applet的一些指导意见吗?
编辑: 经过审查,我想知道我真的需要在这里做异步线程,我可以只为每个COM端口维护状态,并为每个COM端口单独进行流逻辑(即状态机)。
答案 0 :(得分:2)
围绕串口的许多困难都围绕着一个假设。假设串行端口以方便的方式和预期的方式接收数据。
这是一个例子。我知道我的GPS接收器发送线路(以CRLF结束)。这是NMEA句子之一的一个例子:
$ GPGSV,3,1,11,10,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30 * 77
但是,串行端口DataReceived事件处理程序可能(通常在我的PC上)使用该数据块进行多次激活。
事件火灾 - 数据
1 $
2 GPGSV,3,1,11,10
3 ,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30*77
我没有与此作斗争,而是创建了一些在事件触发时接收数据的例程,并将其排队。当我需要数据时,我会调用一些其他例程,将数据重新组合在块大小我想要中。因此,使用我的示例第一次和第二次调用read line(我的readline)时,我得到一个空答案。 我第三次收到整个NMEA的判决。
坏消息是我没有C#。代码在这里SerialPort
根据端口的速度,代表可能不是一个好的选择。我使用委托以接近1Mbps的速度测试我的例程,而不是使用委托。在不使用代表的情况下,这是一个更好的选择。
以下是知情人士的一些提示
答案 1 :(得分:1)
如果你使用背景工作者,你将不会抓小 数据片段,你将获得整个字符串。你需要 类似的东西:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
serialPort1.Open();
if (serialPort1.IsOpen)
{
while (keepReading)
{
backgroundWorker1.ReportProgress(0, serialPort1.ReadLine());
//backgroundWorker1.ReportProgress(0, sentence.Split(','));
// split_gps_data();
}
}
}
}
答案 2 :(得分:0)
处理此问题的.NET方法是使用事件和委托。这将最终创建多个线程,但它将以一种意味着您不显式创建它们的方式这样做。如果您创建一个事件处理程序并将其添加到每个端口的DataReceived事件,那么当任何端口接收数据时,将在单独的线程上调用事件处理程序。当然,这意味着该方法必须是可重入的,并且必须保护对任何共享数据结构的访问以防止并发访问。
您的处理程序例程将执行以下操作:
答案 3 :(得分:-1)
您需要知道接收器以何种速度吐出数据。它是一秒钟,每秒两次,5次......
我有同样的问题阅读GPS数据。您需要在C#中使用backgroundworker来更新变量,屏幕。