Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I update my UI from C# events triggered by serial port data?

I'm a tech-level employee helping out with some of the coding in a manufacturing test environment. The specific question is handling events in C#. Not just Button_click, specifically if I have a stream of data coming through a serial port and have to update the UI in real time according to what is coming in through the serial port. For example, if I have two approaches that both ultimately do the same thing, what is the difference between:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
        this.Invoke(new EventHandler(doSomething));
}

And something like:

void OnGotData(object sender, EventArgs e) {...};
delegate void UpdateCallback(data d);
void doSomething(data d) {
   ...
  if (field.InvokeRequired) {
            UpdateCallback x = doSomething;
            this.Invoke(x, new object[] { d });
  }
  else {
            field.Text = d;
  }
   ...
}

What are the tradeoffs? Is the more convoluted second approach a matter of convention, Could I get away with using the first approach everywhere when real-time performance is important?

like image 635
TerrorTech Avatar asked Jul 23 '13 03:07

TerrorTech


People also ask

Can we update UI from thread?

However, note that you cannot update the UI from any thread other than the UI thread or the "main" thread. To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help: Activity.

How do I refresh the UI in Windows?

Open the task manager and go to the services tab, then look for UIFlowService, right-click on it, and select Restart.

Can we update UI from service in Android?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml. In the above code, we have taken text view, when user gets the data from intent service it will update.

How can I update UI from other than main thread?

In this case, to update the UI from a background thread, you can create a handler attached to the UI thread, and then post an action as a Runnable : Handler handler = new Handler(Looper. getMainLooper()); handler. post(new Runnable() { @Override public void run() { // update the ui from here } });


1 Answers

If i understand: First approach - always call invoke to update UI Second approach - if InvokeRequired returns true call invoke else - just do UI stuff

Now, if we know that handle for control was created and we want just made small and fast UI updates we can use first approach and UI will be responsible, but with Invoke deadlock is still possible. Than if we don't now if the handle for control is created we must call IsHandleCreated to ensure that Invoke will be successfull and will not throw exception. If IsHandleCreated returns false we cannot update via Invoke and we must wait for handle to be created.

Second approach is worse, because field.InvokeRequired may return false if handle for control is not created and when we call field.Text = d; the control's handle may be created on the background thread, isolating the control on a thread without a message pump and making the application unstable.

So as for me this is the better way:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
    {   if (this.IsHandleCreated == false)
        {
        //do some stuff to proper handle creation or just wait for handle creation
        }

        this.BeginInvoke(new EventHandler(doSomething));
    }
}
like image 104
Andriy Vandych Avatar answered Sep 28 '22 10:09

Andriy Vandych