Are you interested in exploring how to generate an event from C# .net assemblies to your LabVIEW application for handling any operations such as event logs, user notifications, user messaging, or any other? you are in the right place, Let's see how to write events in C# and register for these events in LabVIEW.
Let's create a quick C# code to implement events:
Let's start by considering a simple C# class library to implement the functions of a standard calculator. let's add in an additional requirement to generate an event when the calculation function has any invalid inputs, such as generating a divide by zero event notification.
To generate the events, we will be using the concepts of Delegates and Events available in C#.
- Delegate - A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.
- Event - Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.
using System;
namespace Calculator
{
public class StandardCalculator
{
public delegate void CalculationErrorCallback(string errorMessage);
public event CalculationErrorCallback CalculationError;
public double divide(double a, double b)
{
double c = a / b;
if (b == 0)
{
CalculationError($"{DateTime.Now.ToString("dd-MM-yyyy_hh:mm:ss tt")} - Divide by Zero Error: {a}/{b}");
}
return c;
}
}
}
In the above code, we can see that a "CalculationError" event is generated when the second input to the divide function is zero. since the event is of delegate type CalculationErrorCallback, we can pass an errorString to the classes or objects that have registered with this event.
Build the above code as a .Net Assembly using Visual Studio.
Let's now implement the LabVIEW code to capture the events generated by C#:
Using the Standard Calculator .Net Assembly created in the above step, let's first consider an application created in LabVIEW to access the divide method as shown below.
The above-shown LabVIEW code uses the .Net Constructor node to instantiate the StandardCalculator .Net object and Invoke node to access the divide function available in the StandardCalculator class. For more information about using the .Net Constructor node and invoke node to access the methods from a .Net assembly(DLL), please refer to my
blog Calling a C# .Net function in LabVIEW.
Let's now begin with the step-by-step procedure to register and listen to the CalculationError event in LabVIEW and display the error message in a string indicator. This is done by implementing a Callback VI in LabVIEW. The Callback VI will be registered to the event and the VI will get executed automatically whenever the event is generated by C#. Here we start,
Step 1: The first step is to register for the event using the Register Event Callback node. This node can be accessed from the Connectivity->.Net function palette of LabVIEW as shown below.
Step 2: Connect the StandardCalculator .Net object reference to the event source input of the Register Event Callback node.
This will enable the Reg Event Callback node to display all the events available in the .Net object.
Step 3: Select the event to which we would want to register in LabVIEW using the Reg Event Callback node added in the above step.
Since the StandardCalculator has only one event, we are seeing only the CalculationError in the above image. If we have many such events defined in C#, we have to select the required event to be registered.
Step 4: We have registered for the event in the above step, but we need to pass the VI Ref of the Callback VI that needs to be executed when an event is generated by C# .Net Assembly. We don't have to create this VI, LabVIEW does it automatically for us.
Right-click on the VI Ref in Reg Event Callback node and select Create Callback VI.
This will automatically create the VI and wires the static reference of the VI to the Reg Event Callback node.
Step 5: Open the callback VI by double-clicking on the static VI reference shown in the above step and save the VI.
You can now notice that the Callback VI has the "Event Data" as one of the inputs. The datatype of the Event Data will be the same as the parameters defined in C# delegate. So whenever the event is generated in C#, the errorMessage will be passed from the C# event to LabVIEW callback VI.
The generated callback VI has one more input named "User Parameter". The user parameter input can be configured by us while registering for the event in LabVIEW at the Reg Event Callback node.
You can pass any inputs such as control reference or values or clusters to the "User Parameter" of the Reg Event Callback node. Whenever an event is generated by C#, the user parameter wired by the developer while registering for the event will be passed as input to the callback VI.
Step 6: Let's add a string indicator to the front panel of our Demo VI to display the error messages.
Step 7: Now we can pass the reference of the "Error Logs" string indicator to the User Parameter input of the Reg Event Callback node. This will enable the callback VI to access the control reference of the Error Logs indicator when an event is generated by C#.
You can notice that, as we connect the Error Logs reference to the User Parameter input of the Reg Event Callback node, the VI Ref input wire shows a wiring mismatch.
This is because the User Parameter of the Reg Event Callback node is now updated to reference datatype, but the User Parameter defined in the callback VI is still a variant type. The wiring issue will be resolved once we change the datatype of the control in the callback VI.
Quick Tip - to avoid this additional step, try to wire the User Parameter input to the Reg Event Callback node before generating the callback VI. It's a good option to choose User Parameter as a typedef cluster, instead of directly wiring the data. Alternatively, you can also convert the data to a variant and pass it as input to the Reg Event Callback node to avoid this step.
Step 8: This is the last step, code the required program in the callback VI. In our current example, we want to display the error message in the Error Logs indicator, so we will use the reference of the indicator to display(append), the error messages received from C#.
Step 9: Sorry, we missed something important! We should not forget to unregister the event callback before closing the application. The unregistering of the event can be done using Connectivity->.Net->Unregister for Events node in the LabVIEW function palette. Missing to unregister the event will result in memory leaks in LabVIEW.
Now, whenever the event is generated from C#.Net assemblies loaded into LabVIEW, we will be able to capture the events using the callback VI.
Let's try running the application and see how it's working.
I hope this blog was useful, do drop in any comments, questions and suggestions in the comments section of blog.
Written by,
Venkatesh Perumal Pranay C
0 Comments