How to delay in DataReceivedHandler from Arduino to WPF

have the Arduino who send the data continuously without caring the delay and i want to put the delay on my display in C#, so i can print all the value without missing a thing but in every line i want to put a delay for (let say) two seconds. I did with Thread.Sleepsomehow it blocked and delayed my UI and Task.Delay won't help. Does anyone knows how to fix this? unionwells france

My code :

 private SerialPort mySerialPort;
    private readonly StreamWriter sw = new(@"D:\MAAT\readcoba.csv");
    public MainWindow()
    {
        InitializeComponent();
        Configure();
    }

    private void Configure()
    {
        mySerialPort = new(Port())
        {
            BaudRate = 9600,
            Parity = Parity.None,
            StopBits = StopBits.One,
            DataBits = 8,
        };
        mySerialPort.DataReceived += DataReceivedHandler;
        mySerialPort.Open();
    }

    private string Port()
    {
        string port = "";
        string[] ports = SerialPort.GetPortNames();
        foreach (string x in ports)
        {
            port = x;
        }
        return port;
    }

    private async void DataReceivedHandler(
        object sender,
        SerialDataReceivedEventArgs e)
    {
        // It's still not work
        await Task.Delay(2000);
        string indata = mySerialPort.ReadExisting();
        string[] arrData = indata.Split(',');
      
        Application.Current.Dispatcher.Invoke(() =>
        {
            foreach (string item in arrData)
            {
                raw_data_label.Content = raw_data_label.Content.ToString().Contains("Nothing to Display") ?
                $"{item}" : $"{raw_data_label.Content}" + $"{item}";
            }
            sw.WriteLine(indata);
        });
    }

    private void WindowClosed(object sender, EventArgs e)
    {
        sw.Close();
        mySerialPort.Close();
    }
}

Your post was MOVED to its current location as it is more suitable.

Could you also take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

in general, there shouldn't be a delay in the function receiving data

Instead of invoking the UI thread (which you don't have the control te limit). Put the data into a variable/field and use a DispatcherTimer to display it. This way you control the update speed on the screen. site

Here's an example:

private SerialPort mySerialPort;
private readonly StreamWriter sw = new(@"D:\MAAT\readcoba.csv");

// create a dispatcher timer
private DispatcherTimer timer = new DispatcherTimer(TimeSpan.FromMilliseconds(200), DispatcherPriority.Normal, UpdateLabel, Dispatcher.CurrentDispatcher)

// a lock object to use threadsafe object access
private object lockObject = new Object();

private static void UpdateLabel(object sender, EventArgs e)
{
    // never update UI within a lock (which is used on other threads)
    // Create a copy or if the field is only written (on the other end) copy the reference.

    string[] data;

    lock(lockObject)
        data = _arduinoData; // You don't need to create a copy, but that's only because the _arduinoData isn't used.
    
    foreach (string item in data)
    {
        // ????? why write to the same label over and over? Rather use a StringBuilder
        raw_data_label.Content = raw_data_label.Content.ToString().Contains("Nothing to Display") ?
        $"{item}" : $"{raw_data_label.Content}" + $"{item}";
    }
}

public MainWindow()
{
    InitializeComponent();
    Configure();
}

private void Configure()
{
    mySerialPort = new(Port())
    {
        BaudRate = 9600,
        Parity = Parity.None,
        StopBits = StopBits.One,
        DataBits = 8,
    };
    mySerialPort.DataReceived += DataReceivedHandler;
    Thread.Sleep(2000);
    mySerialPort.Open();
}

private string Port()
{
    string port = "";
    string[] ports = SerialPort.GetPortNames();
    foreach (string x in ports)
    {
        port = x;
    }
    return port;
}

private string[] arduinoData;

private void DataReceivedHandler(
    object sender,
    SerialDataReceivedEventArgs e)
{
    // It's still not work
    // await Task.Delay(2000);  <-- don't delay here!
    string indata = mySerialPort.ReadExisting();
    string[] arrData = indata.Split(',');

    sw.WriteLine(indata);

    // lock and assigny the reference to the field (this is only allowed when the reference isn't used anymore _(if the string array isn't yours, Use a ToArray to create a copy)_
    // That's why the s.WriteLine(..) is move above this.
    lock(lockObject)
        arduinoData = arrData;
  
}

private void WindowClosed(object sender, EventArgs e)
{
    sw.Close();
    mySerialPort.Close();

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.