How to repeatedly listen to serial port DataReceived event for timeout no buffer received?

548 Views Asked by At

I have a serial port connection to weighing indicator(display) that connecting to the scale.

Connection diagram

The device B has 3 state:

  1. No Power(Plug off)
  2. Power On(Plug on but not power up)
  3. Display Ready(after press power up)

On any state, I can connect to serial port but I can only get DataReceived event when display ready state (#3). If on certain timeout no value from DataReceived, I need to trigger the screen to alert the user that device is not on ready state. When user press Power On and after the display is ready, then I can revoke the trigger so the screen can continue when DataReceived arrived.

I have try using ManualResetEvent based from what I found:

ManualResetEvent DataReceivedEvent = new ManualResetEvent(false);
private void Open_Click(object sender, RoutedEventArgs e)
{
        // All the port initialization
        _serialPort.Open();
        TimeSpan waitTime = TimeSpan.FromMilliseconds(5000);
        bool noData = DataReceivedEvent.WaitOne(waitTime);
}
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
        SerialPort sp = (SerialPort)sender;
        DataReceivedEvent.Set();
}

The MRE seems promising since I can wait, Set the event so I know the data is received, and return false when WaitOne not Set but it freezing my UI and it just run one time after serial port is open.

Is it possible to put ManualResetEvent under thread to keep loop and wait without freezing UI? I try to search for it but I cannot find it.

1

There are 1 best solutions below

0
On

Based from @kunif suggestion, I have come to use DateTime as a benchmark to see if the device and display is disconnected. The connection status return accordingly on device turn off, display power up and display ready.

private DateTime LastBufferTime;
private bool Running { get; set; } = true;
private void Open_Click(object sender, RoutedEventArgs e)
{
    Running = true;
    LastBufferTime = DateTime.Now;
    _serialPort.DataReceived += SerialPortOnDataReceived;
    _serialPort.Open();
    Task.Run(() => ThreadTimer());
}
private async void ThreadTimer()
{
    while (Running)
    {
        if ((DateTime.Now - LastBufferTime).TotalSeconds > 5)
        {
           // No response from DataReceived
        }
        else
        {
           // Response from DataReceived
        }
    }
}
private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
    SerialPort sp = (SerialPort)sender;
    LastBufferTime = DateTime.Now;
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
    if (_serialPort != null)
    {
        if (_serialPort.IsOpen)
        {
            _serialPort.Close();
        }
        _serialPort.DataReceived -= SerialPortOnDataReceived;
        _serialPort.Dispose();
        Running = false;
    }
}