C# 中通过串口的多端口异步 I/O

发布于 2024-07-15 19:39:18 字数 415 浏览 5 评论 0原文

我正在尝试为串行 I/O (RS-232) 在 C# 中有多个单元,我遇到了一个问题,因为我缺乏线程经验,因此我正在征求有关最著名方法的反馈。

我有一个 COM 端口池 COM1-16,每个端口都可以随时读/写,并且我需要能够同时管理它们。 这是线程池的情况吗? 关于构造这个小程序有哪些指导?

编辑: 经过审查,我想知道我是否真的需要在这里执行异步线程,我可以只维护每个 COM 端口的状态并单独为每个 COM 端口执行流程逻辑(即状态机)。

I'm trying to write a test application for serial I/O (RS-232) with multiple units in C# and I'm running into an issue with my lack of threading experience so I'm soliciting feedback for a best known method.

I've got a pool of COM ports COM1-16 each of which can read/write at any time and I need to be able to manage them simultaneously. Is this a situation for a thread pool? What is some guidance on structuring this applet?

Edit:
Upon review I was wondering is I really even need to do asynchronous threads here, I could just maintain states for each COM-port and do flow logic (i.e., statemachine) for each COM-port individually.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

極樂鬼 2024-07-22 19:39:18

围绕串行端口的大部分困难都集中在一个假设上。 假设串行端口接收到的数据是方便且符合预期的数据块。

这是一个例子。 我知道我的 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 事件处理程序可能(通常在我的电脑上)会使用该数据块多次触发。

事件触发 - 数据

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(my readline) 时,我得到一个空答案。
第三次我得到了整个 NMEA 句子。

坏消息是我不会 C#。 代码在这里 SerialPort

根据端口的速度,代表可能不会一个不错的选择。 我使用委托和不使用委托以接近 1Mbps 的速度测试了我的例程。 在这样的速度下,不使用代表是更好的选择。

以下是知情人士提供的一些提示

金·汉密尔顿

Much of the difficulty surrounding the serial port is centered around an assumption. The assumption is that the serial port receives data in chunks that are convenient, and what is expected.

Here is an example. I know my GPS receiver sends lines (ends with CRLF). This is an example of one of the NMEA sentences:

$GPGSV,3,1,11,10,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30*77

However, the serial ports DataReceived event handler might(usually does on my PC) fire several times with chunks of that data.

event fire - data

1 $
2 GPGSV,3,1,11,10
3 ,75,053,29,29,52,311,32,24,50,298,30,02,39,073,30*77

Instead of fighting this I created some routines that receive data whenever the event fires, and queue it up. When I need the data I call some other routines that put the data back together in chunk sizes I want. So using my example the first and second time I call read line(my readline) I get back an empty answer.
The third time I get the entire NMEA sentence back.

The bad news is that I don't C#. The code is here SerialPort

Depending on the speed of the ports delegates may not be a good choice. I tested my routines at near 1Mbps using delegates, and not using delegates. At those speeds not using delegates was a better choice.

Here are some tips from those in the know

Kim Hamilton

薄暮涼年 2024-07-22 19:39:18

如果你使用后台工作者,你就不会抢小
数据片段,您将获得整个字符串。 你需要
就像是:

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();
            }
        }
    }
}

If you use the backgroundworker you won't be grabbing small
pieces of the data, you'll get the entire string. You need
something like:

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();
            }
        }
    }
}
怪异←思 2024-07-22 19:39:18

处理此问题的 .NET 方法是使用事件和委托。 这最终将创建多个线程,但这样做的方式意味着您无需显式创建它们。 如果您创建一个事件处理程序并将其添加到每个端口的 DataReceived 事件中,那么当任何端口接收数据时,都会在单独的线程上调用该事件处理程序。 当然,这意味着该方法必须是可重入的,并且必须保护对任何共享数据结构的访问免受并发访问。

您的处理程序例程将执行如下操作:

  1. 调用 ReadExisting 以获取可用数据。
  2. 处理数据。
  3. 完毕。

The .NET way to handle this is to use Events and Delegates. This will end up creating multiple threads, but it will do so in a manner that means you don't explicitly create them. If you create an event handler and add it to the DataReceived event of each port, then when any port receives data, the event handler will be called on a separate thread. Naturally, this means the method must be reentrant, and that access to any shared data structures must be protected against concurrent access.

Your handler routine will do something like the following:

  1. Call ReadExisting to get the data available.
  2. Handle data.
  3. Done.
澉约 2024-07-22 19:39:18

您需要知道接收器发出数据的速度。 是每秒一次、每秒两次、5 次...

我在读取 GPS 数据时遇到了同样的问题。 您需要使用 C# 中的后台工作程序来更新您的变量、屏幕。

You need to know at what speed the receiver is spitting out data. Is it once a second, twice a second, 5 times...

I had this same issue reading GPS data. You need to use the backgroundworker in C# to update your variables, screen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文