C#中的多个串行端口/故障使用列表<>;

本文关键字:列表 lt gt 故障 串行端口 | 更新日期: 2023-09-27 18:21:31

我有一个系统,它向串行端口发送"at"命令,并在MessageBox上显示返回。但我需要在所有可用的串行端口中执行此操作。所以我创建了一个列表,并在上面添加所有端口。我成功地发送了命令,但由于处理列表时遇到问题,无法继续执行其余代码以捕获返回。我是C#的初学者。下面是我当前的代码。被评论掉的部分是我正在努力继续的。这部分属于旧代码(当它只是一个串行端口时)。

public partial class Form1 : Form
    {
        List<SerialPort> serialPort = new List<SerialPort>();
        // delegate is used to write to a UI control from a non-UI thread
        private delegate void SetTextDeleg(string text);
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            var portNames = SerialPort.GetPortNames();
            foreach (var port in portNames) {
                SerialPort sp;
                sp = new SerialPort(port, 19200, Parity.None, 8, StopBits.One);
                sp.Handshake = Handshake.None;
                //sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
                sp.ReadTimeout = 500;
                sp.WriteTimeout = 500;
                serialPort.Add(sp);
                listPorts.Items.Add(port);
            }
        }
        private void listPorts_SelectedIndexChanged(object sender, EventArgs e)
        {
        }
        private void button1_Click(object sender, EventArgs e)
        {
            foreach (var sp in serialPort) {
                // Open port
                try
                {
                    if (!sp.IsOpen)
                        sp.Open();
                    MessageBox.Show(sp.PortName + " aberto!");
                    sp.Write("at'r'n");
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error opening/writing to serial port :: " + ex.Message, "Error!");
                }
            }
        }
        /* HELP START
        void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(500);
            string data = sp.ReadLine();
            this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
        }
        private void si_DataReceived(string data)
        {
            String retorno = data.Trim();
            MessageBox.Show(retorno);
            // Fecha a porta após pegar o retorno
            sp.Close();
        }
        HELP END */
    }

要放置的内容'sp.ReadLine();'和"sp.Close();"?我不知道这样做是因为列表<>

C#中的多个串行端口/故障使用列表<>;

最简单的方法是使用lambda表达式,它将捕获您正在使用的端口。lambda表达式是构建委托"内联"的一种方式,它能够使用您在其中声明它的方法中的局部变量。

例如:

foreach (var port in portNames)
{
    // Object initializer to simplify setting properties
    SerialPort sp = new SerialPort(port, 19200, Parity.None, 8, StopBits.One)
    {
        Handshake = Hanshake.None,
        ReadTimeout = 500,
        WriteTimeout = 500
    };
    sp.DataReceived += (sender, args) =>
    {
        Thread.Sleep(500); // Not sure you need this...
        string data = sp.ReadLine();
        Action action = () => {
            MessageBox.Show(data.Trim());
            sp.Close();
        };
        BeginInvoke(action);
    };
    serialPort.Add(sp);
    listPorts.Items.Add(port);
}

关于这个的一些注意事项:

  • 仅仅因为已经接收到一些数据并不意味着整条线路都接收到了,所以ReadLine可能仍然会阻塞
  • 如果需要显示消息框,则可能不需要Control.BeginInvoke。(如果你需要在这里做更多的工作,你可能想把大部分代码提取到一个单独的方法中,只需要一个字符串,然后创建一个调用该方法的操作。)
  • 您确定要在收到第一行后立即关闭串行端口吗

您可以将sp_DataReceived方法更改为,

       void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(500);
            SerialPort sp = (SerialPort)sender;
            string data = sp.ReadLine();
            this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
            sp.Close();
        }

并且从CCD_ 5方法中去除CCD_。

如果您想在si_DataReceived方法中有一个Serial端口值,你应该通过那里:

  // First, add port into your delegate
  private delegate void SetTextDeleg(SerialPort port, string text);
  ...
  /* HELP START */
  void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
  {
    Thread.Sleep(500);
    SerialPort sp = (SerialPort) sender; // <- Obtain the serial port
    string data = sp.ReadLine();
    // Pass the serial port into  si_DataReceived: SetTextDeleg(sp, ...
    this.BeginInvoke(new SetTextDeleg(sp, si_DataReceived), new object[] { data }); 
  }
  // "SerialPort sp" is added
  private void si_DataReceived(SerialPort sp, string data) {
    String retorno = data.Trim();
    MessageBox.Show(retorno);
    // Fecha a porta após pegar o retorno
    sp.Close();
  }
  /* HELP END */

另请参阅:

http://msdn.microsoft.com/library/system.io.ports.serialport.datareceived.aspx