R
In SerialPort, there's a DataReceived event that occurs when data from a consistent port are produced. Asynchronous port communication in 2 (Task) can be used https://msdn.microsoft.com/ru-ru/library/dd449174 and https://msdn.microsoft.com/ru-ru/library/system.threading.cancellationtokensource(v=vs.110).aspx ♪ Order of work:TaskCompletionSource and CancellationTokenSource shall be established upon request to the portFor CancellationTokenSource via Token.Register() the revocation processor shall be added and time shall be displayed.The data are recorded at the port.The task is expected to be completed in the meantime for the TaskCompletionSource.When we get the data from the port, we try to process them.If successful, we will complete the task through the TaskCompletionSource.TrySetResult()In case of error, the task is completed through the TaskCompletionSource.TrySetException()In the case of a timemaut, Cancellation TokenSource will work.Example of class with the above-mentioned conduct:class ModemConnection : IDisposable
{
private readonly SerialPort _serialPort;
private bool _disposed;
private TaskCompletionSource<Frame> _taskCompletionSource = new TaskCompletionSource<Frame>();
public TimeSpan Timeout { get; set; }
public ModemConnection(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
_serialPort.DataReceived += _serialPort_DataReceived;
}
private async Task<Frame> SendFrame(Frame frame)
{
var cts = new CancellationTokenSource();
_taskCompletionSource = new TaskCompletionSource<Frame>();
cts.Token.Register(tcs => ((TaskCompletionSource<Frame>)tcs).TrySetCanceled(), _taskCompletionSource, false);
cts.CancelAfter(Timeout);
var bw = new BinaryWriter(_serialPort.BaseStream, Encoding.ASCII, true);
frame.Write(bw);
bw.Flush();
Task.Run(() => OnOnFrameSent(frame));
return await _taskCompletionSource.Task.ConfigureAwait(false);
}
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var r = new BinaryReader(new BufferedStream(_serialPort.BaseStream), Encoding.ASCII, true);
var frame = new Frame();
frame.Read(r);
_taskCompletionSource?.TrySetResult(frame);
Task.Run(() => OnOnFrameReceived(frame));
}
catch (Exception ex)
{
_taskCompletionSource?.TrySetException(ex);
}
}
public event EventHandler<Frame> FrameReceived;
protected virtual void OnOnFrameReceived(Frame e)
{
FrameReceived?.Invoke(this, e);
}
public event EventHandler<Frame> FrameSent;
protected virtual void OnOnFrameSent(Frame e)
{
FrameSent?.Invoke(this, e);
}
public void Open()
{
if (_serialPort.IsOpen) return;
_serialPort.Open();
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_serialPort.Dispose();
}
}