2012-01-12 19 views
5

SerialPort'da bazı zaman uyumsuz IO'yu yapan bir winform programım var. Bununla birlikte, SerialPort.Close() çağrısında donma gibi görünen programla periyodik olarak bir soruna rastlıyorum.C# SerialPort.Close üzerinde donma dondurma

Bu bir iş parçacığı güvenlik sorunu olduğunu düşünüyorum, ancak, nasıl düzeltileceğinden emin değilim. Bağlantı noktası açma/kapama işlevleriyle async DataReceived eylemcisini ekleme/çıkarma ve bağlantı noktasındaki giriş ve çıkış arabelleklerini atmayı denedim, ancak hiçbir şey yapmıyor gibi görünüyor. Ben önemli SerialPort kod aşağıda düşünüyorum:

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. 
    } 
    } 
} 

GÜNCELLEME için

Teşekkür @ UI iş parçacığı ile kilitlenme durumu (This blog post nitelendirerek iyi bir iş yapar ve diğer birçok verir işaret Afrin cevabı iyi ipuçları), basit bir değişiklik yaptım ve henüz hatayı yeniden üretemedim! (bu genellikle çağırmak arayarak) çünkü SerialPort nesne

Sen ana iş parçacığı ile çağrı senkronize ediyoruz işleyicisi olay öyle kapattığınızda asarlar

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

    ThreadPool.QueueUserWorkItem(handleReceivedBytes); 

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

private void handleReceivedBytes(object state) 
{ 
    //Do the more interesting handling of the receivedBytes list here. 
} 

cevap

13

sebep. SerialPort'un yakın yöntemi, DataReceived/Error/PinChanged olaylarını sonlandırmak için kullanılan EventLoopRunner iş parçacığı için bekler. Ancak olaydaki kendi kodunuz da ana iş parçacığının yanıt vermesini beklediğinden, kilitlenme durumuna geçersiniz.

çözüm: Invoke yerine BeginInvoke kullanın: https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application

referans: http://stackoverflow.com/a/3176959/146622

+0

Ben özetle 'Oku' arasında 'SerialPort' içinde kilitlenme var, doğru anlamak emin olmak için 'Kapat' diyor? – chezy525

+0

port_DataReceived olay işleyicisindeki UI öğesi güncellemelerini değiştirme şeklinizi değiştirmelisiniz, Invoke yerine güncellemek için BeginInvoke özelliğini kullanın veya çözümde açıklandığı gibi olayı işlemek için başka bir iş parçacığı kullanın. – Afshin

+0

UI'nin verilerini farklı bir iş parçacığında işleme koymak sorunu çözmüş görünüyor. Teşekkürler! – chezy525

İlgili konular