Tobia Tobia - 9 months ago 51
C# Question

Digital input to events with C#

I have a digital input/output board to listen and control with a C# service. This board has its library with simple methods like

. I would like to build a high-level class to manage this board using events connected to signal meanings but I don't know what can be more suitable for this purpose using C# libraries.

For example, I have:

Input signal n.1 : error_state (1=error 0=ok)

and I need en event like

public void ErrorRaised(int errorcode)

My questions are:

  • Do you agree that there is no other way then an endless loop to read signals?

  • Can I attach something like an "observer" for a particular variable that throws an event when a variable changes (like the watch window of visual studio debug)? Otherwise I may check the value for each loop and manually throw an event.

  • Do you agree I need at least two threads, one for the signal read loop and another one to do events work?

Answer Source

Without knowing the underlying board a lot of this is just guessing.

If the library/board doesn't provide any other access type than reading, there is no other way than an endless loop to fire the events, but it's strange to not have some interrupt handling on the board, usually you can configure GPIO's to detect signal changes, maybe the board has that capability but the library lacks support for it, or may be there really is support for it, recheck the library, if no then you must use the endless loop.

The event, I would use an EventHandler as usual:

public class SignalEventArgs : EventArgs
    public int SignalValue{ get; set; }

public event EventHandler<SignalEventArgs> ErrorChange;

//To fire it:
if(ErrorChange != null)
    ErrorChange(this, new SignalEventArgs{ SignalValue = value; })

The data observer, yes, there is binding which matches exactly that behavior (even if it's dessigned usually for UI and datasources, you can check the INotifyPropertyChanged implementation for more info), but for something simple like signals, unless you have a lot or there can be unknown signal channels is a lot easier to create an array with the current status and when you read a channel compare with the stored value and if changes update the array value and fire the event.

About multiple threads, it depends on your needs, if you can't miss a single change then yes, you need a thread to read continuously the data, have some type of map with all the input states and whenever a change happens store the change in some type of queue, then signal a second thread to consume these events and rise them. Another approach can be to use the threadpool for this, just queue a task whenever a change happens, but this doesn't guarantee the event order. Finally, if you can accept missing a fast change then there's no need of multithreading, just execute the loop and whenever you find a change fire the event.