Subscribe to changes of multiple OPC items. The
IEasyDAClient.ItemChanged event will be generated for each significant item change. Callback methods will be invoked if they are specified in the argument objects.
Syntax
Parameters
- itemSubscriptionArgumentsArray
- Array of arguments, one element per each OPC item involved in the operation.
Return Value
The function returns an array of integer handles. Each such handle uniquely identifies the item subscription. The indices of elements in the output array are the same as those in the input array, .
Exceptions
Exception | Description |
System.ArgumentNullException | A null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument. |
Example
// This example shows how subscribe to changes of multiple items and display each change, identifying the different
// subscriptions by an integer.
using System;
using System.Threading;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;
namespace DocExamples.DataAccess._EasyDAClient
{
partial class SubscribeMultipleItems
{
public static void StateAsInteger()
{
// Instantiate the client object.
using (var client = new EasyDAClient())
{
// Hook events
client.ItemChanged += client_StateAsInteger_ItemChanged;
Console.WriteLine("Subscribing...");
int[] handleArray = client.SubscribeMultipleItems(new[]
{
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000,
state: 1), // An integer we have chosen to identify the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000,
state: 2), // An integer we have chosen to identify the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000,
state: 3), // An integer we have chosen to identify the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000,
state: 4) // An integer we have chosen to identify the subscription
});
for (int i = 0; i < handleArray.Length; i++)
Console.WriteLine($"handleArray[{i}]: {handleArray[i]}");
Console.WriteLine("Processing item changed events for 10 seconds...");
Thread.Sleep(10 * 1000);
Console.WriteLine("Unsubscribing...");
}
Console.WriteLine("Waiting for 5 seconds...");
Thread.Sleep(5 * 1000);
Console.WriteLine("Finished.");
}
// Item changed event handler
static void client_StateAsInteger_ItemChanged(object sender, EasyDAItemChangedEventArgs eventArgs)
{
// Obtain the integer state we have passed in.
var stateAsInteger = (int)eventArgs.Arguments.State;
// Display the data
if (eventArgs.Succeeded)
Console.WriteLine($"{stateAsInteger}: {eventArgs.Vtq}");
else
Console.WriteLine($"{stateAsInteger} *** Failure: {eventArgs.ErrorMessageBrief}");
}
}
}
// This example shows how subscribe to changes of multiple items and display each change, identifying the different
// subscriptions by an object.
using System;
using System.Threading;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;
namespace DocExamples.DataAccess._EasyDAClient
{
partial class SubscribeMultipleItems
{
class CustomObject
{
public CustomObject(string name)
{
Name = name;
}
public string Name { get; }
}
public static void StateAsObject()
{
// Instantiate the client object.
using (var client = new EasyDAClient())
{
// Hook events
client.ItemChanged += client_StateAsObject_ItemChanged;
Console.WriteLine("Subscribing...");
int[] handleArray = client.SubscribeMultipleItems(new[]
{
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000,
new CustomObject("First")), // A custom object that corresponds to the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000,
new CustomObject("Second")), // A custom object that corresponds to the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000,
new CustomObject("Third")), // A custom object that corresponds to the subscription
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000,
new CustomObject("Fourth")) // A custom object that corresponds to the subscription
});
for (int i = 0; i < handleArray.Length; i++)
Console.WriteLine($"handleArray[{i}]: {handleArray[i]}");
Console.WriteLine("Processing item changed events for 10 seconds...");
Thread.Sleep(10 * 1000);
Console.WriteLine("Unsubscribing...");
}
Console.WriteLine("Waiting for 5 seconds...");
Thread.Sleep(5 * 1000);
Console.WriteLine("Finished.");
}
// Item changed event handler
static void client_StateAsObject_ItemChanged(object sender, EasyDAItemChangedEventArgs eventArgs)
{
// Obtain the custom object we have passed in.
var stateAsObject = (CustomObject)eventArgs.Arguments.State;
// Display the data
if (eventArgs.Succeeded)
Console.WriteLine($"{stateAsObject.Name}: {eventArgs.Vtq}");
else
Console.WriteLine($"{stateAsObject.Name} *** Failure: {eventArgs.ErrorMessageBrief}");
}
}
}
// This example shows how to store current state of the subscribed items in a dictionary.
using System;
using System.Collections.Generic;
using System.Threading;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;
namespace DocExamples.DataAccess._EasyDAClient
{
partial class SubscribeMultipleItems
{
public static void StoreInDictionary()
{
// Instantiate the client object.
using (var client = new EasyDAClient())
{
client.ItemChanged += client_ItemChanged_StoreInDictionary;
Console.WriteLine("Subscribing item changes...");
client.SubscribeMultipleItems(
new[] {
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, null),
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, null),
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, null),
new DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, null)
});
Console.WriteLine("Processing item changed events for 1 minute...");
int startTickCount = Environment.TickCount;
do
{
Thread.Sleep(5*1000);
// Each 5 seconds, display the current state of the items we have subscribed to.
lock (_serialize)
{
Console.WriteLine();
foreach (KeyValuePair<DAItemDescriptor, DAVtqResult> pair in _vtqResultDictionary)
{
DAItemDescriptor itemDescriptor = pair.Key;
DAVtqResult vtqResult = pair.Value;
Console.WriteLine($"{itemDescriptor}: {vtqResult}");
}
// The code above shows how you can process the complete contents of the dictionary. In other
// scenarios, you may want to access just a specific entry in the dictionary. You can achieve that
// by indexing the dictionary by the item descriptor of the item you are interested in.
}
} while (Environment.TickCount < startTickCount + 60*1000);
Console.WriteLine("Unsubscribing item changes...");
}
Console.WriteLine("Finished.");
}
// Item changed event handler
static void client_ItemChanged_StoreInDictionary(object sender, EasyDAItemChangedEventArgs e)
{
lock (_serialize)
// Convert the event arguments to a DAVtq result object, and store it in the dictionary under the key which
// is the item descriptor of the item this item changed event is for.
_vtqResultDictionary[e.Arguments.ItemDescriptor] = (DAVtqResult)e;
}
// Holds last known state of each subscribed item.
private static readonly Dictionary<DAItemDescriptor, DAVtqResult> _vtqResultDictionary =
new Dictionary<DAItemDescriptor, DAVtqResult>();
// Synchronization object used to prevent simultaneous access to the dictionary.
private static readonly object _serialize = new object();
}
}
' This example shows how to store current state of the subscribed items in a dictionary.
Imports System.Threading
Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.OperationModel
Namespace DataAccess._EasyDAClient
Partial Friend Class SubscribeMultipleItems
Public Shared Sub StoreInDictionary()
' Instantiate the client object.
Using client = New EasyDAClient()
AddHandler client.ItemChanged, AddressOf client_ItemChanged_StoreInDictionary
Console.WriteLine("Subscribing item changes...")
client.SubscribeMultipleItems(New DAItemGroupArguments() {
New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, Nothing),
New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, Nothing),
New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, Nothing),
New DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Register_I4", 1000, Nothing)
})
Console.WriteLine("Processing item changed events for 1 minute...")
Dim startTickCount As Integer = Environment.TickCount
Do
Thread.Sleep(5 * 1000)
' Each 5 seconds, display the current state of the items we have subscribed to.
SyncLock _serialize
Console.WriteLine()
For Each pair As KeyValuePair(Of DAItemDescriptor, DAVtqResult) In _vtqResultDictionary
Dim itemDescriptor As DAItemDescriptor = pair.Key
Dim vtqResult = pair.Value
Console.WriteLine($"{itemDescriptor}: {vtqResult}")
Next
' The code above shows how you can process the complete contents of the dictionary. In other
' scenarios, you may want to access just a specific entry in the dictionary. You can achieve that
' by indexing the dictionary by the item descriptor of the item you are interested in.
End SyncLock
Loop While Environment.TickCount < startTickCount + 60 * 1000
Console.WriteLine("Unsubscribing item changes...")
End Using
Console.WriteLine("Finished.")
End Sub
' Item changed event handler
Private Shared Sub client_ItemChanged_StoreInDictionary(ByVal sender As Object, ByVal e As EasyDAItemChangedEventArgs)
SyncLock _serialize
' Convert the event arguments to a DAVtq result object, and store it in the dictionary under the key which
' is the item descriptor of the item this item changed event is for.
_vtqResultDictionary(e.Arguments.ItemDescriptor) = CType(e, DAVtqResult)
End SyncLock
End Sub
' Holds last known state of each subscribed item.
Private Shared ReadOnly _vtqResultDictionary As New Dictionary(Of DAItemDescriptor, DAVtqResult)
' Synchronization object used to prevent simultaneous access to the dictionary.
Private Shared ReadOnly _serialize As New Object
End Class
End Namespace
Requirements
Target Platforms: .NET Framework: Windows 10 (selected versions), Windows 11 (selected versions), Windows Server 2012 R2, Windows Server 2016; .NET: Linux, macOS, Microsoft Windows
See Also