2012-01-12 141 views
5

SerialPortでいくつかの非同期IOを実行するwinformプログラムがあります。しかし、私は定期的にSerialPort.Close()呼び出しでプログラムがフリーズしているように見えます。SerialPortでWinformがフリーズします。閉じる

私はスレッドセーフの問題だと思っていますが、もしあれば修正する方法がわかりません。私は、ポートのオープン/クローズ機能を使って非同期のDataReceivedハンドラを追加/削除しようとしましたが、ポートの入出力バッファを破棄しましたが、何もしないようです。私は重要なSerialPortコードは以下のだと思う:アフリンの答えはUIスレッドでデッドロック状態を指摘@へ

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

おかげで(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'内のデッドロックがあります'Close'コール? – chezy525

+0

port_DataReceivedイベントハンドラでUI要素の更新を呼び出す方法を変更したり、BeginInvokeを使用してInvokeの代わりに更新したり、ソリューションの説明どおりに別のスレッドを使用してイベントを処理する必要があります。 – Afshin

+0

UIのデータを別のスレッドで処理すると、問題が解決したようです。ありがとう! – chezy525

関連する問題