我有一個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做得很好描述它,並給出了其他幾個好的提示),我做了一個簡單的改變,並且還沒有能夠重現錯誤呢!
爲了確保我理解正確的話,在總結,還有的'Read'之間的'SerialPort'內的僵局'關閉'電話? – chezy525 2012-01-12 22:37:49
您必須更改在Port_DataReceived事件處理程序中調用UI元素更新的方式,使用BeginInvoke來更新而不是Invoke,或者如解決方案中所述使用另一個線程來處理事件。 – Afshin 2012-01-12 22:47:15
在另一個線程上處理UI的數據似乎解決了這個問題。謝謝! – chezy525 2012-01-12 23:31:47