2015-04-21 34 views
0

我做了一個快速搜索,仍然無法找到我的問題的答案。在後臺工作者關閉com端口時應用程序崩潰 - C#應用程序?

串口變量

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

回答

1
string data = _serialPort.ReadLine(); 

沒有缺少潛在麻煩同意本聲明。當這個通話沒有完成時,你手上有一個非常令人討厭的故障模式。不必這樣做,您可以在錯誤的時間關閉串口設備,拔掉電纜,使線路終結器損壞,您將頭痛不已。

只有在任何事件處理程序停止運行時,SerialPort.Close()方法才能完成。這可以顯着增加死鎖的機率。使用ReadLine()方法很好,但是你也需要將ReadTimeout屬性設置爲10秒,這樣你才能確保事故不會變成不可解決的問題。讓TimeoutException或者終止你的程序或者設置一個「串口已經死了」的狀態變量。

通過將SerialPort的生命週期與表單的生命週期解除關聯,進一步提高成功機率。通常情況下,唯一明智的做法是在程序啓動時創建實例,並在程序終止前不關閉它。只需將它保存在一個單獨的類中,它可以是靜態以使其易於使用。

而且,直覺上來說,根本不需要調用Close()。終結者將照顧它。

另外請確保,如果您使用USB模擬器,至從來沒有斷開它,而不通過安全刪除硬件托盤圖標。 USB驅動程序通常處理非常糟糕的意外刪除。有些非常差,即使您打開設備,設備也會消失。並試圖關閉它總是失敗,你不能幹淨退出你的程序了。

+0

感謝您的回答!其實,這只是回到我的第一個想法的方式:在我的程序啓動時打開一個端口! – JKW