的方法,我们正在使用我们的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