2012-01-12 65 views
5

我有一個winform程序,在SerialPort上執行一些異步IO。但是,我定期遇到程序在SerialPort.Close()調用中凍結的問題,這似乎是隨機的。C#Winform凍結SerialPort.Close

我認爲這是一個線程安全問題,但我不知道如何解決它。我試着用port open/close函數添加/刪除異步DataReceived處理程序,並丟棄端口上的輸入和輸出緩衝區,但它似乎沒有做任何事情。我認爲重要的SerialPort代碼如下:

using System; 
using System.Collections.Generic; 
using System.IO.Ports; 

public class SerialComm 
{ 
    private object locker = new object(); 

    private SerialPort port; 
    private List<byte> receivedBytes; 

    public SerialComm(string portName) 
    { 
    port = new SerialPort(portName); 
    port.BaudRate = 57600; 
    port.Parity = Parity.None; 
    port.DataBits = 8; 
    port.StopBits = StopBits.One; 

    receivedBytes = new List<byte>(); 
    } 

    public void OpenPort() 
    { 
    if(port!=null && !port.IsOpen){ 
     lock(locker){ 
     receivedBytes.Clear(); 
     } 

     port.DataReceived += port_DataReceived; 
     port.Open(); 
    } 
    } 

    public void ClosePort() 
    { 
    if(port!=null && port.IsOpen){ 
     port.DataReceived -= port_DataReceived; 
     while(!(port.BytesToRead==0 && port.BytesToWrite==0)){ 
     port.DiscardInBuffer(); 
     port.DiscardOutBuffer(); 
     } 
     port.Close(); 
    } 
    } 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
    try{ 
     byte[] buffer = new byte[port.BytesToRead]; 
     int rcvdBytes = port.Read(buffer, 0, buffer.Length); 

     lock(locker){ 
     receivedBytes.AddRange(buffer); 
     } 

     //Do the more interesting handling of the receivedBytes list here. 

    } catch (Exception ex) { 
     System.Diagnostics.Debug.WriteLine(ex.ToString()); 
     //put other, more interesting error handling here. 
    } 
    } 
} 

UPDATE

感謝@ Afrin的回答指出與UI線程死鎖狀態(This blog post做得很好描述它,並給出了其他幾個好的提示),我做了一個簡單的改變,並且還沒有能夠重現錯誤呢!

​​

回答

13

,當你關閉它是因爲在你的SerialPort對象

你同步與主線程調用的事件處理程序(通常通過調用調用),它會掛起的原因。 SerialPort的close方法等待它的EventLoopRunner線程觸發DataReceived/Error/PinChanged事件終止。但由於您在事件中的代碼也在等待主線程響應,所以會遇到死鎖情況。

解決方案:使用的BeginInvoke,而不是調用的: https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application

參考:http://stackoverflow.com/a/3176959/146622

+0

爲了確保我理解正確的話,在總結,還有的'Read'之間的'SerialPort'內的僵局'關閉'電話? – chezy525 2012-01-12 22:37:49

+0

您必須更改在Port_DataReceived事件處理程序中調用UI元素更新的方式,使用BeginInvoke來更新而不是Invoke,或者如解決方案中所述使用另一個線程來處理事件。 – Afshin 2012-01-12 22:47:15

+0

在另一個線程上處理UI的數據似乎解決了這個問題。謝謝! – chezy525 2012-01-12 23:31:47