2

シリアルポートを介してPCに接続されたGSMモデムからのATコマンドへの応答を解析するプログラムを作成しています。このプログラムには、シリアルポート上のすべての応答を「リッスン」するスレッドがあります。次に、コマンドの実行を要求したスレッドのキューに応答を送信するか(アイテムがこのキューに投稿されている間はブロックされます)、非送信請求結果コードの受信を通知するイベントを生成できます。

現在、スレッド(メソッド)はSerialPort.ReadLineメソッドに基づいており、私が作成した「GsmModem」というクラスの一部です。GsmModem.Close()メソッドが呼び出されたとき。「リスナー」スレッドに終了するように通知し、終了するのを待ってから、シリアルポートを閉じる必要があります。私の現在のコードは、シリアルポートのタイムアウト例外に依存しているため、あまり洗練されていません。スレッドはserialPort.ReadLine()でスピンし、タイムアウト例外をスローし、ManualResetEventフラグをチェックします。私は本当にこれを避けたいです。

SerialPort.Readline()の呼び出しを中止できるかどうかをどこでも調べましたが、唯一の解決策はタイムアウト例外のようです。

他の可能な方法は、SerialPort.DataReceivedイベントを使用してデータを処理し、新しい行を受信したときにデータをキューに入れるか、一方的な応答を受信したときに新しいイベントを発生させることです(これが良いアイデアかどうかはわかりません)。

実際のコードは次のようになります。

private void ModemListenerThread()
{
    if (this._serialPort.IsOpen)
    {
        //Execute the thread wile we don't receive the "endThreadSignal"
        while(!this._endThreadEvent.WaitOne(0))
        {
            // Catch TimeoutException and spin checking for the ManualResetEvent
            try
            {
                // Read line
                string line = this._serialPort.ReadLine();
                if (String.IsNullOrWhiteSpace(line))
                    continue;
                //Check if no command was sent (not definitive code)
                if (_modemIsIdle)
                    this.OnUnsolicitedResponse(new EventArgs());
                else
                {
                    //Enqueue as reply to command()
                    lock ((this._itemQueue as ICollection).SyncRoot)
                    {
                        _itemQueue.Enqueue(line);
                        this._itemPostedEvent.Set();
                    }
                }
            }
            //Timeout is necessary to avoid the thread to block indefinitely
            catch (TimeoutException ex)
            {
                continue;
            }
        }
    }
}

返信の処理を実装する方法についての提案をいただければ幸いです。ここでの私の主な質問は、readlineへの呼び出しを中止することは可能ですか?そうでない場合、SerialPort.DataRecevedイベントにロジックを実装できますか?それは推奨されますか?最後に、もっと良いものを提案できれば、それは素晴らしいことです。

コメントや助けてくれてありがとう。

4

1 に答える 1

1

イベントの利用をお勧めしSerialPort.DataReceivedます。シリアルデータ用に独自のバッファを維持することを意味しますが、それはそれほど複雑ではありません。これを行うと、リスナースレッドを維持する必要がなくなります。代わりに、シリアルポートを閉じる準備ができたら、DataReceivedデリゲートを削除してポートを閉じます。

SerialPort.ErrorReceivedイベントも処理することをお勧めします。あなたはすでにこれをしているかもしれません。

于 2011-02-10T04:16:57.550 に答える