简体   繁体   English

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

[英]Multiple Serial Ports in C# / Trouble using List <>

I have a system that sends an "at" command to a serial port and displays the return on a MessageBox. 我有一个将“ at”命令发送到串行端口并在MessageBox上显示返回信息的系统。 But I needed to do this in all available serial ports. 但是我需要在所有可用的串行端口中执行此操作。 So I created a List and I'm adding all the ports on it. 因此,我创建了一个列表,并添加了所有端口。 I managed to send the command, but could not continue the rest of the code to catch the return because I am having trouble handling the lists. 我设法发送了命令,但由于无法处理列表,因此无法继续执行其余代码以获取返回信息。 I am a beginner in C #. 我是C#的初学者。 Below is my current code. 下面是我当前的代码。 The part that is commented out is what I'm struggling to continue. 被注释掉的部分是我正在努力继续进行的工作。 This part belongs to the old code (when it was just one serial port). 这部分属于旧代码(当它只是一个串行端口时)。

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 */

    }

What to put in place 'sp.ReadLine ();' 放置在什么位置'sp.ReadLine();' and 'sp.Close ();'? 和'sp.Close();'? I don't know do this because of the List <> 我不知道这样做是因为列表<>

The simplest approach would be to use a lambda expression which would capture the port you're using. 最简单的方法是使用一个lambda表达式 ,它将捕获您正在使用的端口。 A lambda expression is a way of building a delegate "inline" - and one which is able to use the local variables from the method you declare it in. Lambda表达式是一种构建“内联”委托的方法-一种能够使用您在其中声明其方法的局部变量的方法。

For example: 例如:

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

A few notes about this: 关于此的一些注意事项:

  • Just because some data has been received doesn't mean that a whole line has, so ReadLine may still block 仅仅因为已接收到一些数据并不意味着整行都已接收,所以ReadLine可能仍会阻塞
  • If you only need to show a message box, you may not need Control.BeginInvoke . 如果需要显示一个消息框,则可能不需要Control.BeginInvoke (If you need to do more here, you might want to extract most of that code into a separate method which just takes a string, then create an action which would call that method.) (如果您需要在此处执行更多操作,则可能需要将大部分代码提取到一个仅包含字符串的单独方法中,然后创建一个调用该方法的操作。)
  • Are you sure you want to close the serial port as soon as the first line has been received? 您确定要在收到第一行后立即关闭串行端口吗?

You can chage your sp_DataReceived method as, 您可以将sp_DataReceived方法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();
        }

and remove the sp.Close(); 并删除sp.Close(); from si_DataReceived method. 来自si_DataReceived方法。

If you want to have a Serial port value in your si_DataReceived method, you should pass it there: 如果要在si_DataReceived方法中具有串行端口值,则应在此处传递它:

  // 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 */

See also: 也可以看看:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM