串口操作网上应该有大量的文章,这里就不多解释了,在使用SerialPort时,关闭时总会遇到死锁,网上有其他人的代码虽然能解决死锁,但是会陷入一个死循环当中,导致程序不能退出,这篇文章可以解决这个问题,废话少说,直接上代码:
SerialPort spMain = new SerialPort(); //端口
bool Listening = false;//是否在读取数据
bool Closing = false;//是否在关闭串口
delegate void AddContent(byte[] received);
event AddContent addContent;
public SerialTest()
{
InitializeComponent();
InitPort("COM3");
}
void InitPort(string portName)
{
if (SerialPort.GetPortNames().ToList().IndexOf(portName) == -1)
{
MessageBox.Show("没有找到" + portName + "端口!\n");
return;
}
spMain.PortName = portName;
spMain.DataBits = 8;
spMain.Parity = Parity.None;
spMain.StopBits = StopBits.One;
spMain.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
this.addContent += new AddContent(ProcessData);
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Closing) return;//如果正在关闭串口,就不读取数据
try
{
Listening = true;//开始读取数据。
byte[] readBuffer = new byte[spMain.BytesToRead];
spMain.Read(readBuffer, 0, readBuffer.Length);
addContent(readBuffer);
}
finally
{
Listening = false;//读取数据完毕
if (Closing) ClosePort(spMain); //读完数据若需要关闭串口,则调用关闭串口方法,这样就解决了卡在Application.DoEvents()了。
}
}
void ProcessData(byte[] receivedData)
{
this.BeginInvoke(new MethodInvoker(delegate {
txtContent.AppendText(new ASCIIEncoding().GetString(receivedData);
}));
}
private void Open_Click(object sender, EventArgs e)
{
if (spMain == null) return;
if (button1.Text == "开始")
{
button1.Text = "停止";
spMain.Open();
}
else
{
button1.Text = "开始";
ClosePort(spMain);
}
}
/// <summary>
/// 关闭串口
/// </summary>
/// <param name="sp"></param>
void ClosePort(SerialPort sp)
{
if (sp != null && sp.IsOpen)
{
Closing = true;
if (Listening) return; //如果正在读取数据,则不关闭串口
sp.Close();
Closing = false;
}
}