Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#/中的多个串行端口使用列表时出现问题<&燃气轮机;_C#_.net_Serial Port_Virtual Serial Port - Fatal编程技术网

C#/中的多个串行端口使用列表时出现问题<&燃气轮机;

C#/中的多个串行端口使用列表时出现问题<&燃气轮机;,c#,.net,serial-port,virtual-serial-port,C#,.net,Serial Port,Virtual Serial Port,我有一个系统,它向串行端口发送一个“at”命令,并在MessageBox上显示返回值。 但我需要在所有可用的串行端口中执行此操作。所以我创建了一个列表,并在其中添加所有端口。 我成功地发送了命令,但无法继续执行其余代码以捕获返回,因为我在处理列表时遇到了问题。我是C#的初学者。 下面是我当前的代码。 被注释掉的部分是我正在努力继续的部分。 这部分属于旧代码(当它只是一个串行端口时) 公共部分类表单1:表单 { List serialPort=新列表(); //委托用于从非UI线程写入UI控件 私

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

公共部分类表单1:表单
{
List serialPort=新列表();
//委托用于从非UI线程写入UI控件
私有委托void SetTextDeleg(字符串文本);
公共表格1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
var portNames=SerialPort.GetPortNames();
foreach(端口名中的var端口){
串行端口sp;
sp=新串行端口(端口,19200,奇偶校验。无,8,停止位。1);
sp.握手=握手。无;
//sp.DataReceived+=新的SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReadTimeout=500;
sp.WriteTimeout=500;
serialPort.Add(sp);
listPorts.Items.Add(端口);
}
}
私有无效列表端口\u SelectedIndexChanged(对象发送方,事件参数e)
{
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
foreach(serialPort中的var sp){
//开放端口
尝试
{
如果(!sp.IsOpen)
sp.Open();
MessageBox.Show(sp.PortName+“aberto!”);
sp.Write(“at\r\n”);
}
捕获(例外情况除外)
{
MessageBox.Show(“打开/写入串行端口时出错::”+例如消息,“错误!”);
}
}
}
/*帮助启动
无效sp_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
睡眠(500);
字符串数据=sp.ReadLine();
this.BeginInvoke(新的SetTextDeleg(si_DataReceived),新对象[]{data});
}
接收到私有void si_数据(字符串数据)
{
String returno=data.Trim();
MessageBox.Show(否);
//这是一个非常好的选择
sp.Close();
}
帮助结束*/
}
如何放置“sp.ReadLine();”和“sp.Close();”?
我不知道该怎么做,因为列表中列出了最简单的方法是使用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
    。(如果您需要在这里做更多的工作,您可能希望将大部分代码提取到一个单独的方法中,该方法只需要一个字符串,然后创建一个调用该方法的操作。)
  • 确实要在收到第一行后立即关闭串行端口吗

    • 最简单的方法是使用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\u数据接收方法更改为

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

      并移除
      sp.Close()来自
      si_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();
              }
      

      并移除
      sp.Close()
      来自
      si_DataReceived
      方法。

      如果希望在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 */
      
      //首先,将端口添加到代理中
      私有委托void SetTextDeleg(SerialPort端口,字符串文本);
      ...
      /*帮助启动*/
      无效sp_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
      {
      睡眠(500);
      
      SerialPort sp=(SerialPort)sender;//如果希望在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 */
      
      //首先,将端口添加到代理中
      私有委托void SetTextDeleg(SerialPort端口,字符串文本);
      ...
      /*帮助启动*/
      无效sp_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
      {
      睡眠(500);
      
      SerialPort sp=(SerialPort)sender;//谢谢!它起作用了,但问题是MessageBox看起来是空的。为什么会发生这种情况?正确的返回应该是“ok”,但MessageBox没有显示任何内容。请参见Putty和C#:Putty>/C#35;>@JuninhoChr:可能它先读取一个空行,然后关闭端口?对于su来说很难说老实说,我会从一个控制台应用程序开始,它会使这类事情更容易调试,我说