0

1バイトだけでなく、全行を受信した後に関数を呼び出すイベントが必要です。

.NET の SerialPort オブジェクトには、DataReceived、ErrorReceived、PinChanged の 3 つのイベントがあります。

DataReceived を使用している場合 - イベントは 1 バイト後、または「ReceiveByteThreshold」プロパティで定義された「x」バイト後に「起動」しています。行の長さが異なる場合があるため、「x」を予測することはできません。

誰かが私にヒントを与えることができますか?

LF/CRLFまでバイトを収集するバッファを作成する必要がありますか、それとも問題へのより良いアプローチがありますか?

4

4 に答える 4

7

これを取得することはできません。唯一のオプションは、DataReceived イベント ハンドラー呼び出しを遅延させるための SerialPort.ReceivedBytesThreshold であり、可変長の応答には役に立ちません。

回避策は非常に簡単です。DataReceived イベント ハンドラで ReadLine() を呼び出すだけです。これはワーカー スレッドでブロックされ、プログラムで実行中の他の処理には影響しません。ReadLine() 呼び出しがブロックされている間に追加のイベントが発生しても危険はなく、SerialPort クラス内でインターロックされます。通信の信頼性が十分でなく、ReadLine() が永久にブロックされない場合は、必要に応じて ReadTimeout プロパティを使用します。可能な限り最長の応答を受信する際に予想される遅延の 10 倍に設定します。

于 2012-10-01T14:18:08.283 に答える
4

自分でやる必要があります。DataReceived を使用して、各バイトを確認します。改行を取得するまでバッファ内のバイトを収集し、その時点でバッファを行として処理します。

于 2012-10-01T13:47:58.740 に答える
0

これは、迅速に実装された、ブロックされていない、同じスレッドのソリューションです。これは、'\r' と '\n' を待機し、バッファリングされたすべての文字を解析のために送信する、非常に基本的なステート マシンです。ステートマシン自体を変更することで、必要な改行値に変更できます。このアプローチでは、OnNewLineReceived イベントに登録し、SerialStringMessgae イベント ハンドラーからのデータを処理できます。try/catch のオーバーヘッドはありません。デッドロックはありません。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace NonBlockingSerialPortReadLine
{
    public partial class Form1 : Form
    {
    System.IO.Ports.SerialPort sp = new System.IO.Ports.SerialPort();
    public event EventHandler OnNewLineReceived;
    System.Windows.Forms.Timer NewDataTimer = new System.Windows.Forms.Timer();
    int StateMachine = 0;
    StringBuilder stringBuffer = new StringBuilder();

    public Form1()
    {
        InitializeComponent();
        InitTimer();
        InitOnNewLineReceived();
    }

    private void InitTimer()
    {
        NewDataTimer.Interval = 50;
        NewDataTimer.Tick += NewDataTimer_Tick;
    }

    private void InitOnNewLineReceived()
    {
        OnNewLineReceived += Form1_OnNewLineReceived;
    }

    void Form1_OnNewLineReceived(object sender, EventArgs e)
    {
        SerialStringMessgae STM = e as SerialStringMessgae;
        string messgae = STM.message;

        // PARSE YOU MESSAGE HERE - the debug line below is not mandatory

        System.Diagnostics.Debug.WriteLine(messgae);
    }

    class SerialStringMessgae : EventArgs
    {
        public string message;
    }

    private void StartListeningButton_Click(object sender, EventArgs e)
    {
        StartListeningButton.Enabled = false;
        sp = new System.IO.Ports.SerialPort("COM4",57600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
        try
        {
            sp.Open();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
            return;
        }
        if (sp.IsOpen)
        {
            NewDataTimer.Enabled = true;
        }

    }

    void NewDataTimer_Tick(object sender, EventArgs e)
    {
        string newData = sp.ReadExisting();
        foreach (char c in newData)
        {
            switch (StateMachine)
            {
                case 0:
                    // waiting for '\r'
                    if (c == '\r')
                    {
                        StateMachine = 1;
                    }
                    else
                    {
                        stringBuffer.Append(c);
                    }
                    break;
                case 1:
                    // waiting for '\n'
                    if (c == '\n')
                    {
                        if (OnNewLineReceived != null)
                        {
                            SerialStringMessgae STM = new SerialStringMessgae();
                            STM.message = stringBuffer.ToString();
                            OnNewLineReceived(this, STM);
                        }
                    }
                    // after parsing the message we reset the state machine
                    stringBuffer = new StringBuilder();
                    StateMachine = 0;
                    break;
            }
        }
    }

}
}
于 2016-07-25T09:19:29.517 に答える
0

ヒント:

このSerialPortクラスには、 ReadLineNewLineメソッドの呼び出しの終了を解釈するために使用される値を設定するプロパティがあります。

于 2012-10-01T14:01:02.240 に答える