[英]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: 关于此的一些注意事项:
ReadLine
may still block ReadLine
可能仍会阻塞 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.) 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.