我做了一个快速搜索,仍然无法找到我的问题的答案。
串口变量
int close;
SerialPort _serialPort = new SerialPort("COM1", 1200, Parity.None, 8, StopBits.One);
串口代理码
private void si_DataReceived(string data)
{
if (close == 1)
{
string d1 = data.Trim().Replace("TT", "");
d1 = d1.Replace("Tl3", "");
txtCan.Text = d1;
}
else
{
return;
}
}
private delegate void SetTextDeleg(string text);
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = _serialPort.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
连接按钮代码
private void button4_Click(object sender, EventArgs e)
{
if (button4.Text == "Close Connection")
{
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.MarqueeAnimationSpeed = 0;
close=0;
try
{
string d1 = txtCan.Text;
double r1 = Convert.ToDouble(d1) * 10;
txtCan.Text = Math.Round(r1, 3).ToString();
button4.Text = "Open Connection";
button1.Enabled = true;
readOnly(true);
}
catch (Exception ex)
{
button4.Text = "Open Connection";
button1.Enabled = true;
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.MarqueeAnimationSpeed = 0;
MessageBox.Show("Cant connect.");
}
}
else
{
progressBar1.Style = ProgressBarStyle.Marquee;
progressBar1.MarqueeAnimationSpeed = 30;
close = 1;
txtCan.Text = "";
txtCan.Focus();
readOnly(false);
button1.Enabled = false;
button4.Text = "Close Connection";
try
{
if(!_serialPort.IsOpen)
{
_serialPort.Handshake = Handshake.None;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
_serialPort.Open();
}
}
catch
{
button4.Text = "Open Connection";
button1.Enabled = true;
readOnly(true);
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.MarqueeAnimationSpeed = 0;
MessageBox.Show("Cant connect.");
}
}
}
我关闭com端口的解决方案,但如果我在可数次重新打开一个表单(如两次或三次,那么它会崩溃),它将会失败。
private void myForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_serialPort.IsOpen)
{
e.Cancel = true;
Thread CloseDown = new Thread(new ThreadStart(CloseSerialOnExit));
CloseDown.Start();
}
}
private void CloseSerialOnExit()
{
try
{
backgroundWorker1.RunWorkerAsync();
}
catch (Exception ex)
{
}
this.BeginInvoke(new EventHandler(NowClose));
}
private void NowClose(object sender, EventArgs e)
{
this.Close(); //now close the form
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
_serialPort.Close();
}
答案 0 :(得分:1)
string data = _serialPort.ReadLine();
此声明不存在潜在的问题。当这个电话没有完成时,你的手上有一个非常讨厌的失败模式。它没有必要,您可以在错误的时间关闭串行设备,猛拉电缆,使线路终结器损坏,您将会非常头疼。
在任何事件处理程序停止运行之前,SerialPort.Close()方法无法完成。这可以显着增加死锁的几率。使用ReadLine()方法很好,但是还必须将ReadTimeout属性设置为10秒,这样您就可以确保事故不会变成不可解决的问题。让TimeoutException终止你的程序或设置一个"串口已经死了"状态变量。
通过将SerialPort的生命周期与表单的生命周期取消关联,进一步提高成功几率。一般来说,唯一明智的做法是在程序启动时创建实例,而不是关闭它直到程序终止。只需将它保存在一个单独的类中,它可以是 static ,以便于使用。
而且,毫不直观地,现在调用Close()已经不再重要了。终结者会照顾它。
如果您使用USB仿真器,请确保从不断开连接,而无需通过安全删除硬件托盘图标。 USB驱动程序通常很难处理意外删除。有些是如此糟糕,以至于即使你打开设备也会让设备消失。并试图关闭它总是失败,你不能再干净地退出你的程序。