我有一个系统向串口发送“at”命令并在MessageBox上显示返回值。 但我需要在所有可用的串口中执行此操作。所以我创建了一个List,并在其中添加了所有端口。 我设法发送命令,但无法继续其余的代码来捕获返回,因为我无法处理列表。我是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();'? 由于List&lt;&gt;
,我不知道这样做答案 0 :(得分:3)
最简单的方法是使用 lambda表达式来捕获您正在使用的端口。 lambda表达式是一种构建委托的方式&#34; inline&#34; - 并且能够使用您声明它的方法中的局部变量。
例如:
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
。 (如果您需要在此处执行更多操作,您可能希望将大部分代码提取到一个单独的方法中,该方法只接受一个字符串,然后创建一个可以调用该方法的操作。)答案 1 :(得分:1)
您可以将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
。
答案 2 :(得分:0)
如果要在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 */
另见:
http://msdn.microsoft.com/library/system.io.ports.serialport.datareceived.aspx