2012-01-12 45 views
5

Tôi có chương trình winform thực hiện một số IO không đồng bộ trên SerialPort. Tuy nhiên, tôi định kỳ chạy vào một vấn đề với chương trình đóng băng trên các cuộc gọi SerialPort.Close(), dường như ngẫu nhiên.C# Đóng băng Winform trên SerialPort.Close

Tôi nghĩ rằng đó là sự cố về an toàn chủ đề nhưng tôi không chắc chắn cách khắc phục sự cố nếu có. Tôi đã thử thêm/gỡ bỏ trình xử lý async DataReceived với các cổng mở/đóng các chức năng và loại bỏ các bộ đệm trong và ngoài trên cổng, nhưng nó dường như không làm bất cứ điều gì. Tôi nghĩ rằng điều quan trọng SerialPort code đang dưới đây:

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

CẬP NHẬT

Nhờ @ câu trả lời Afrin của chỉ ra những điều kiện bế tắc với thread UI (This blog post làm một công việc tốt mô tả nó, và đưa ra một vài khác lời khuyên tốt), tôi đã thực hiện một thay đổi đơn giản và chưa thể tạo lại lỗi!

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

Trả lời

13

Lý do nó sẽ treo khi bạn đóng nó lại là do trong xử lý sự kiện của đối tượng SerialPort bạn

Bạn đang đồng bộ hóa một cuộc gọi với các chủ đề chính (thường là bằng cách gọi gọi). Phương thức đóng của SerialPort đợi chuỗi EventLoopRunner của nó, nó kích hoạt các sự kiện DataReceived/Error/PinChanged để chấm dứt. nhưng vì mã của riêng bạn trong sự kiện cũng đang chờ chủ đề chính phản hồi, bạn gặp phải tình huống khóa chết.

giải pháp: sử dụng BeginInvoke thay vì invoke: https://connect.microsoft.com/VisualStudio/feedback/details/202137/serialport-close-hangs-the-application

tham khảo: http://stackoverflow.com/a/3176959/146622

+0

Để chắc chắn rằng tôi hiểu bạn một cách chính xác, trong Tóm lại, có một bế tắc trong 'SerialPort' giữa' Read' và Các cuộc gọi 'Close'? – chezy525

+0

bạn phải thay đổi cách bạn gọi cập nhật phần tử giao diện người dùng trong trình xử lý sự kiện port_DataReceived, sử dụng BeginInvoke để cập nhật thay vì Gọi hoặc được mô tả trong giải pháp sử dụng một chuỗi khác để xử lý sự kiện. – Afshin

+0

Xử lý dữ liệu cho giao diện người dùng trên một chủ đề khác dường như đã giải quyết được sự cố. Cảm ơn! – chezy525

Các vấn đề liên quan