的方法,我們正在使用我們的SerialPort
處理程序是,以有一個AutoResetEvent
一旦有來自港口的答覆就會收到通知。
SerialPort
FrameWork的類有幾個與集成DataReceived
事件有關的問題。如果沒有可用的完整軟件包(如果您定義了答案長度),有時會被解僱。所以你應該檢查你期望的答案長度。
我們非常精簡的實現:
public class Serialport
{
private SerialPort _serialPort;
private List<byte> _buffer;
private AutoResetEvent _autoResetEvent;
private const int WriteTimeOut = 5;
private event EventHandler ReceivedDataChanged;
public Serialport()
{
_serialPort = new SerialPort();
// set PortName, BaudRate etc
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.DataReceived += ReceiveData;
}
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
var bytes = _serialPort.BytesToRead;
byte[] buffer = new byte[bytes];
if (_serialPort.IsOpen)
{
_serialPort.BaseStream.Read(buffer, 0, bytes);
_buffer.AddRange(buffer);
}
ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray()));
_buffer.Clear();
}
private void SendData(byte[] message, int answerLength)
{
_serialPort.ReceivedBytesThreshold = answerLength;
_serialPort.WriteTimeout = WriteTimeOut;
_serialPort.Write(message, 0, message.Length);
}
public string SendDataCommand()
{
if (_serialPort.IsOpen)
{
ReceivedDataChanged += InterpretAnswer;
SendData(message, length);
if (_autoResetEvent.WaitOne(100))
{
ReceivedDataChanged -= InterpretAnswer;
//Data Received and interpreted and send to the caller
return _requestAnswer;
}
ReceivedDataChanged -= InterpretAnswer;
}
return "Connection not open";
}
private void InterpretAnswer(object sender, EventArgs e)
{
// handle all interpretation
// Set the event
_autoResetEvent.Set();
}
}
一個串口被初始化並打開。之後,我們連接所有需要的事件,並致電SendDataCommand()
方法。該方法是從某個任務調用的公共可見方法。這稱爲方法SendData
。只要有答案,就會觸發事件並開始解釋。如果在指定的時間內完成解釋(_autoResetEvent.WaitOne(msToWait)
),則結果返回給調用方法。 這應該在一個單獨的任務中完成,所以當你等待答案時,UI將不會阻止。
如上所述,這是一個非常簡明的例子。您應該在收到的SerialPort處理程序中執行更多檢查,因爲該事件存在一些問題。通過這種方法,您將對業務邏輯有更多的抽象。
希望這會有所幫助。
感謝您的信息 – Ditn