OPC Studio User's Guide and Reference
SubscribeMultipleItems Method (_EasyDAClient)
Example 



OpcLabs.EasyOpcClassic Assembly > OpcLabs.EasyOpc.DataAccess.ComTypes Namespace > _EasyDAClient Interface : SubscribeMultipleItems Method
Array of arguments, one element per each OPC item involved in the operation.
Subscribe to changes of multiple OPC items. The OpcLabs.EasyOpc.DataAccess.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
'Declaration
 
<ElementsNotNullAttribute()>
<NotNullAttribute()>
Function SubscribeMultipleItems( _
   ByVal itemSubscriptionArgumentsArray As Object _
) As Object()
'Usage
 
Dim instance As _EasyDAClient
Dim itemSubscriptionArgumentsArray As Object
Dim value() As Object
 
value = instance.SubscribeMultipleItems(itemSubscriptionArgumentsArray)
[ElementsNotNull()]
[NotNull()]
object[] SubscribeMultipleItems( 
   object itemSubscriptionArgumentsArray
)
[ElementsNotNull()]
[NotNull()]
array<Object^>^ SubscribeMultipleItems( 
   Object^ itemSubscriptionArgumentsArray
) 

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, itemSubscriptionArgumentsArray.
Exceptions
ExceptionDescription

A null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument.

This is a usage error, i.e. it will never occur (the exception will not be thrown) in a correctly written program. Your code should not catch this exception.

Remarks
The size of the input array will become the size of the output array. The element positions (indices) in the output array are the same as in the input array.

 

This method operates (at least in part) asynchronously, with respect to the caller. The actual execution of the operation may be delayed, and the outcome of the operation (if any) is provided to the calling code using an event notification, callback, or other means explained in the text. In a properly written program, this method does not throw any exceptions. You should therefore not put try/catch statements or similar constructs around calls to this method. The only exceptions thrown by this method are for usage errors, i.e. when your code violates the usage contract of the method, such as passing in invalid arguments or calling the method when the state of the object does not allow it. Any operation-related errors (i.e. errors that depend on external conditions that your code cannot reliably check) are indicated by the means the operation returns its outcome (if any), which is described in the text. For more information, see Do not catch any exceptions with asynchronous or multiple-operation methods.
Example

.NET

.NET

.NET

COM

COM

// This example shows how subscribe to changes of multiple items and display each change, identifying the different
// subscriptions by an integer.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

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 integer.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.DataAccess import *
from OpcLabs.EasyOpc.DataAccess.OperationModel import *


# Item changed event handler.
def itemChanged(sender, eventArgs):
    # Obtain the integer state we have passed in.
    stateAsInteger = int(eventArgs.Arguments.State)
    if eventArgs.Succeeded:
        print(stateAsInteger, ': ', eventArgs.Vtq, sep='')
    else:
        print(stateAsInteger, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='')


# Instantiate the client object.
client = EasyDAClient()
# Hook events.
client.ItemChanged += itemChanged

print('Subscribing item changes...')
handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000,
                         1),    # an integer we have chosen to identify the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000,
                         2),    # an integer we have chosen to identify the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000,
                         3),    # an integer we have chosen to identify the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000,
                         4),    # an integer we have chosen to identify the subscription
    ])

for i in range(len(handleArray)):
    print('handleArray[', i, ']: ', handleArray[i], sep='')

print('Processing item change notifications for 1 minute...')
time.sleep(60)

print('Unsubscribing all items...')
client.UnsubscribeAllItems()

client.ItemChanged -= itemChanged

print('Finished.')
' This example shows how subscribe to changes of multiple items and display each change, identifying the different
' subscriptions by an integer.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports System.Threading
Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.OperationModel

Namespace DataAccess._EasyDAClient
    Partial Friend Class SubscribeMultipleItems
        Public Shared Sub StateAsInteger()
            ' Instantiate the client object.
            Using client = New EasyDAClient()
                AddHandler client.ItemChanged, AddressOf client_StateAsInteger_ItemChanged

                Console.WriteLine("Subscribing...")
                Dim handleArray() As Integer = client.SubscribeMultipleItems(New DAItemGroupArguments() {
                    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 i As Integer = 0 To handleArray.Length - 1
                    Console.WriteLine($"handleArray[{i}]: {handleArray(i)}")
                Next i

                Console.WriteLine("Processing item changed events for 10 seconds...")
                Thread.Sleep(10 * 1000)

                Console.WriteLine("Unsubscribing...")
            End Using

            Console.WriteLine("Waiting for 5 seconds...")
            Thread.Sleep(5 * 1000)

            Console.WriteLine("Finished.")
        End Sub

        ' Item changed event handler
        Private Shared Sub client_StateAsInteger_ItemChanged(ByVal sender As Object, ByVal eventArgs As EasyDAItemChangedEventArgs)
            ' Obtain the integer state we have passed in.
            Dim stateAsInteger As Integer = CInt(eventArgs.Arguments.State)

            If eventArgs.Succeeded Then
                Console.WriteLine($"{stateAsInteger}: {eventArgs.Vtq}")
            Else
                Console.WriteLine($"{stateAsInteger} *** Failure: {eventArgs.ErrorMessageBrief}")
            End If
        End Sub
    End Class
End Namespace
// This example shows how subscribe to changes of multiple items and display each change, identifying the different
// subscriptions by an object.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

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 subscribe to changes of multiple items and display each change, identifying the different
# subscriptions by an object.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.DataAccess import *
from OpcLabs.EasyOpc.DataAccess.OperationModel import *


class CustomObject(object):
    def __init__(self, name):
        self.name = name


# Item changed event handler.
def itemChanged(sender, eventArgs):
    # Obtain the custom object we have passed in.
    stateAsObject = eventArgs.Arguments.State
    if eventArgs.Succeeded:
        print(stateAsObject.name, ': ', eventArgs.Vtq, sep='')
    else:
        print(stateAsObject.name, ' *** Failure: ', eventArgs.ErrorMessageBrief, sep='')


# Instantiate the client object.
client = EasyDAClient()
# Hook events.
client.ItemChanged += itemChanged

print('Subscribing item changes...')
handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000,
                         CustomObject('First')),    # a custom object that corresponds to the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000,
                         CustomObject('Second')),   # a custom object that corresponds to the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000,
                         CustomObject('Third')),    # a custom object that corresponds to the subscription
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000,
                         CustomObject('Fourth')),   # a custom object that corresponds to the subscription
    ])

for i in range(len(handleArray)):
    print('handleArray[', i, ']: ', handleArray[i], sep='')

print('Processing item change notifications for 1 minute...')
time.sleep(60)

print('Unsubscribing all items...')
client.UnsubscribeAllItems()

client.ItemChanged -= itemChanged

print('Finished.')
' This example shows how subscribe to changes of multiple items and display each change, identifying the different
' subscriptions by an object.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports System.Threading
Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.OperationModel

Namespace DataAccess._EasyDAClient
    Partial Friend Class SubscribeMultipleItems

        Private Class CustomObject
            Sub New(name As String)
                Me.Name = name
            End Sub

            Public ReadOnly Property Name As String
        End Class

        Public Shared Sub StateAsObject()
            ' Instantiate the client object.
            Using client = New EasyDAClient()
                AddHandler client.ItemChanged, AddressOf client_StateAsObject_ItemChanged

                Console.WriteLine("Subscribing...")
                Dim handleArray() As Integer = client.SubscribeMultipleItems(New DAItemGroupArguments() {
                    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 i As Integer = 0 To handleArray.Length - 1
                    Console.WriteLine($"handleArray[{i}]: {handleArray(i)}")
                Next i

                Console.WriteLine("Processing item changed events for 10 seconds...")
                Thread.Sleep(10 * 1000)

                Console.WriteLine("Unsubscribing...")
            End Using

            Console.WriteLine("Waiting for 5 seconds...")
            Thread.Sleep(5 * 1000)

            Console.WriteLine("Finished.")
        End Sub

        ' Item changed event handler
        Private Shared Sub client_StateAsObject_ItemChanged(ByVal sender As Object, ByVal eventArgs As EasyDAItemChangedEventArgs)
            ' Obtain the custom object we have passed in.
            Dim stateAsObject As CustomObject = CType(eventArgs.Arguments.State, CustomObject)

            If eventArgs.Succeeded Then
                Console.WriteLine($"{stateAsObject.Name}: {eventArgs.Vtq}")
            Else
                Console.WriteLine($"{stateAsObject.Name} *** Failure: {eventArgs.ErrorMessageBrief}")
            End If
        End Sub
    End Class
End Namespace
// This example shows how to store current state of the subscribed items in a dictionary.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

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.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import threading
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.DataAccess import *
from OpcLabs.EasyOpc.DataAccess.OperationModel import *


lock = threading.Lock()
vtqResultDictionary = {}

# Item changed event handler.
def itemChanged(sender, eventArgs):
    global lock
    global vtqResultDictionary
    with lock:
        # 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[eventArgs.Arguments.ItemDescriptor] = EasyDAItemChangedEventArgs.ToDAVtqResult(eventArgs)


# Instantiate the client object.
client = EasyDAClient()
# Hook events.
client.ItemChanged += itemChanged

print('Subscribing item changes...')
handleArray = IEasyDAClientExtension.SubscribeMultipleItems(client, [
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000, None),
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Ramp (1 min)', 1000, None),
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Trends.Sine (1 min)', 1000, None),
    DAItemGroupArguments('', 'OPCLabs.KitServer.2', 'Simulation.Register_I4', 1000, None),
    ])

for i in range(len(handleArray)):
    print('handleArray[', i, ']: ', handleArray[i], sep='')

print('Processing item change notifications for 1 minute...')
endTime = time.time() + 60
while time.time() < endTime:
    time.sleep(5)
    #
    # Each 5 seconds, display the current state of the items we have subscribed to.
    with lock:
        print()
        print('Current state of the items:')
        for itemDescriptor, vtqResult in vtqResultDictionary.items():
            print(itemDescriptor, ': ', vtqResult, sep='')
        #
        # 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.

print()
print('Unsubscribing all items...')
client.UnsubscribeAllItems()

client.ItemChanged -= itemChanged

print('Finished.')
' This example shows how to store current state of the subscribed items in a dictionary.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

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
// This example shows how to subscribe to changes of a single OPC XML-DA item and display the value of the item with each change.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  TSubscribeItem_ClientEventHandlers = class
    // Item changed event handler
    procedure OnItemChanged(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyDAItemChangedEventArgs);
  end;

procedure TSubscribeItem_ClientEventHandlers.OnItemChanged(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyDAItemChangedEventArgs);
begin
  if eventArgs.Succeeded then
    WriteLn(eventArgs.Vtq.ToString)
  else  
    WriteLn('*** Failure: ', eventArgs.ErrorMessageBrief);
end;

class procedure SubscribeItem.MainXml;
var
  Arguments: OleVariant;
  Client: TEasyDAClient;
  ClientEventHandlers: TSubscribeItem_ClientEventHandlers;
  HandleArray: OleVariant;
  ItemSubscriptionArguments1: _EasyDAItemSubscriptionArguments;
begin
  ItemSubscriptionArguments1 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments1.ServerDescriptor.UrlString := 'http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx';
  ItemSubscriptionArguments1.ItemDescriptor.ItemID := 'Dynamic/Analog Types/Int';
  ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate := 1000;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := ItemSubscriptionArguments1;

  // Instantiate the client object and hook events
  Client := TEasyDAClient.Create(nil);
  ClientEventHandlers := TSubscribeItem_ClientEventHandlers.Create;
  Client.OnItemChanged := ClientEventHandlers.OnItemChanged;

  WriteLn('Subscribing...');
  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleItems(Arguments));

  WriteLn('Processing item changed events for 1 minute...');
  PumpSleep(60*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllItems;

  WriteLn('Waiting for 5 seconds...');
  PumpSleep(5*1000);

  VarClear(HandleArray);
  VarClear(Arguments);
  FreeAndNil(Client);
  FreeAndNil(ClientEventHandlers);
end;
// This example shows how to subscribe to changes of a single OPC XML-DA item and display the value of the item with each change.
//
// Some related documentation: http://php.net/manual/en/function.com-event-sink.php . Pay attention to the comment that says 
// "Be careful how you use this feature; if you are doing something similar to the example below, then it doesn't really make 
// sense to run it in a web server context.". What they are trying to say is that processing a web request should be 
// a short-lived code, which does not fit well with the idea of being subscribed to events and received them over longer time. 
// It is possible to write such code, but it is only useful when processing the request is allowed to take relatively long. Or, 
// when you are using PHP from command-line, or otherwise - not to serve a web page directly.
// 
// Subscribing to QuickOPC-COM events in the context of PHP Web application, while not imposing the limitations to the request 
// processing time, has to be "worked around", e.g. using the "event pull" mechanism.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

class DEasyDAClientEvents {
    function ItemChanged($varSender, $varE)
    {
        if ($varE->Succeeded)
        {
        print $varE->Vtq->ToString();
            print "\n";
        }
        else
        {
            printf("*** Failure: %s\n", $varE->ErrorMessageBrief);
        }
    }
}

$ItemSubscriptionArguments1 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments");
$ItemSubscriptionArguments1->ServerDescriptor->UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx";
$ItemSubscriptionArguments1->ItemDescriptor->ItemID = "Dynamic/Analog Types/Int";
$ItemSubscriptionArguments1->GroupParameters->RequestedUpdateRate = 1000;

$arguments[0] = $ItemSubscriptionArguments1;

// Instantiate the client object.
$Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient");
$Events = new DEasyDAClientEvents();
com_event_sink($Client, $Events, "DEasyDAClientEvents");

print "Subscribing...\n";
$handles = $Client->SubscribeMultipleItems($arguments);

print "Processing item changed events for 1 minute...\n";
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 60);

print "Unsubscribing...\n";
$Client->UnsubscribeAllItems;

print "Waiting for 5 seconds...\n";
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5);
Rem This example shows how to subscribe to changes of a single OPC XML-DA item and display the value of the item with each change.
Rem
Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

' The client object, with events
'Public WithEvents Client2 As EasyDAClient

Private Sub SubscribeItem_MainXml_Command_Click()
    OutputText = ""
    
    Dim ItemSubscriptionArguments1 As New EasyDAItemSubscriptionArguments
    ItemSubscriptionArguments1.serverDescriptor.UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx"
    ItemSubscriptionArguments1.ItemDescriptor.ItemId = "Dynamic/Analog Types/Int"
    ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate = 1000

    Dim arguments(0) As Variant
    Set arguments(0) = ItemSubscriptionArguments1

    ' Instantiate the client object and hook events
    Set Client2 = New EasyDAClient

    OutputText = OutputText & "Subscribing..." & vbCrLf
    Dim handleArray() As Variant
    handleArray = Client2.SubscribeMultipleItems(arguments)
    
    OutputText = OutputText & "Processing item changed events for 1 minute..." & vbCrLf
    Pause 60000

    OutputText = OutputText & "Unsubscribing..." & vbCrLf
    Client2.UnsubscribeAllItems

    OutputText = OutputText & "Waiting for 5 seconds..." & vbCrLf
    Pause 5000

    OutputText = OutputText & "Finished." & vbCrLf
    Set Client2 = Nothing
End Sub

Public Sub Client2_ItemChanged(ByVal sender As Variant, ByVal eventArgs As EasyDAItemChangedEventArgs)
    If eventArgs.Succeeded Then
        OutputText = OutputText & eventArgs.vtq & vbCrLf
    Else
        OutputText = OutputText & "*** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf
    End If
End Sub
Rem This example shows how to subscribe to changes of a single OPC XML-DA item and display the value of the item with each change.
Rem
Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Option Explicit

Dim ItemSubscriptionArguments1: Set ItemSubscriptionArguments1 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments")
ItemSubscriptionArguments1.ServerDescriptor.UrlString = "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx"
ItemSubscriptionArguments1.ItemDescriptor.ItemID = "Dynamic/Analog Types/Int"
ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate = 1000

Dim arguments(0)
Set arguments(0) = ItemSubscriptionArguments1

Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
WScript.ConnectObject Client, "Client_"

WScript.Echo "Subscribing..."
Dim handles: handles = Client.SubscribeMultipleItems(arguments)


WScript.Echo "Processing item changed events for 1 minute..."
WScript.Sleep 60*1000

WScript.Echo "Unsubscribing..."
Client.UnsubscribeAllItems

WScript.Echo "Waiting for 5 seconds..."
WScript.Sleep 5*1000

WScript.DisconnectObject Client
Set Client = Nothing


' Item changed event handler
Sub Client_ItemChanged(Sender, e)
    If e.Succeeded Then
    WScript.Echo e.Vtq
    Else
        WScript.Echo "*** Failure: " & e.ErrorMessageBrief
    End If
End Sub
// This example shows how to subscribe to changes of multiple items and display the value of the item with each change.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  TSubscribeMultipleItems_ClientEventHandlers = class
    // Item changed event handler
    procedure OnItemChanged(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyDAItemChangedEventArgs);
  end;

procedure TSubscribeMultipleItems_ClientEventHandlers.OnItemChanged(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyDAItemChangedEventArgs);
begin
  if eventArgs.Succeeded then
    WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ': ', eventArgs.Vtq.ToString)
  else
    WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ' *** Failure: ', eventArgs.ErrorMessageBrief);
end;

class procedure SubscribeMultipleItems.Main;
var
  Arguments: OleVariant;
  Client: TEasyDAClient;
  ClientEventHandlers: TSubscribeMultipleItems_ClientEventHandlers;
  HandleArray: OleVariant;
  ItemSubscriptionArguments1: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments2: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments3: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments4: _EasyDAItemSubscriptionArguments;
begin
  ItemSubscriptionArguments1 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments1.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments1.ItemDescriptor.ItemID := 'Simulation.Random';
  ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate := 1000;

  ItemSubscriptionArguments2 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments2.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments2.ItemDescriptor.ItemID := 'Trends.Ramp (1 min)';
  ItemSubscriptionArguments2.GroupParameters.RequestedUpdateRate := 1000;

  ItemSubscriptionArguments3 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments3.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments3.ItemDescriptor.ItemID := 'Trends.Sine (1 min)';
  ItemSubscriptionArguments3.GroupParameters.RequestedUpdateRate := 1000;

  ItemSubscriptionArguments4 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments4.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments4.ItemDescriptor.ItemID := 'Simulation.Register_I4';
  ItemSubscriptionArguments4.GroupParameters.RequestedUpdateRate := 1000;

  Arguments := VarArrayCreate([0, 3], varVariant);
  Arguments[0] := ItemSubscriptionArguments1;
  Arguments[1] := ItemSubscriptionArguments2;
  Arguments[2] := ItemSubscriptionArguments3;
  Arguments[3] := ItemSubscriptionArguments4;

  // Instantiate the client object and hook events
  Client := TEasyDAClient.Create(nil);
  ClientEventHandlers := TSubscribeMultipleItems_ClientEventHandlers.Create;
  Client.OnItemChanged := ClientEventHandlers.OnItemChanged;

  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleItems(Arguments));

  WriteLn('Processing item changed events for 1 minute...');
  PumpSleep(60*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllItems;

  WriteLn('Waiting for 5 seconds...');
  PumpSleep(5*1000);

  WriteLn('Finished.');
  VarClear(HandleArray);
  VarClear(Arguments);
  FreeAndNil(Client);
  FreeAndNil(ClientEventHandlers);
end;
// This example shows how to subscribe to changes of multiple items and display the value of the item with each change.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

class DEasyDAClientEvents {
    function ItemChanged($varSender, $varE)
    {
        if ($varE->Succeeded)
        {
            printf(" s\n", $varE->Arguments->ItemDescriptor->ItemId, $varE->Vtq->ToString());
        }
        else
        {
            printf("*** Failure: %s\n", $varE->ErrorMessageBrief);
        }
    }
}

$ItemSubscriptionArguments1 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments");
$ItemSubscriptionArguments1->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2";
$ItemSubscriptionArguments1->ItemDescriptor->ItemID = "Simulation.Random";
$ItemSubscriptionArguments1->GroupParameters->RequestedUpdateRate = 1000;

$ItemSubscriptionArguments2 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments");
$ItemSubscriptionArguments2->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2";
$ItemSubscriptionArguments2->ItemDescriptor->ItemID = "Trends.Ramp (1 min)";
$ItemSubscriptionArguments2->GroupParameters->RequestedUpdateRate = 1000;

$ItemSubscriptionArguments3 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments");
$ItemSubscriptionArguments3->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2";
$ItemSubscriptionArguments3->ItemDescriptor->ItemID = "Trends.Sine (1 min)";
$ItemSubscriptionArguments3->GroupParameters->RequestedUpdateRate = 1000;

$ItemSubscriptionArguments4 = new COM("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments");
$ItemSubscriptionArguments4->ServerDescriptor->ServerClass = "OPCLabs.KitServer.2";
$ItemSubscriptionArguments4->ItemDescriptor->ItemID = "Simulation.Register_I4";
$ItemSubscriptionArguments4->GroupParameters->RequestedUpdateRate = 1000;

$arguments[0] = $ItemSubscriptionArguments1;
$arguments[1] = $ItemSubscriptionArguments2;
$arguments[2] = $ItemSubscriptionArguments3;
$arguments[3] = $ItemSubscriptionArguments4;

$Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient");
$Events = new DEasyDAClientEvents();
com_event_sink($Client, $Events, "DEasyDAClientEvents");

$Client->SubscribeMultipleItems($arguments);

print "Processing item changed events for 1 minute...\n";
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 60);
REM This example shows how to subscribe to changes of multiple items and display the value of the item with each change.
REM
REM Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

' The client object, with events
'Public WithEvents Client2 As EasyDAClient

Private Sub SubscribeMultipleItems_Main_Command_Click()
    OutputText = ""
    
    Dim itemSubscriptionArguments1 As New EasyDAItemSubscriptionArguments
    itemSubscriptionArguments1.serverDescriptor.ServerClass = "OPCLabs.KitServer.2"
    itemSubscriptionArguments1.ItemDescriptor.itemId = "Simulation.Random"
    itemSubscriptionArguments1.GroupParameters.requestedUpdateRate = 1000

    Dim itemSubscriptionArguments2 As New EasyDAItemSubscriptionArguments
    itemSubscriptionArguments2.serverDescriptor.ServerClass = "OPCLabs.KitServer.2"
    itemSubscriptionArguments2.ItemDescriptor.itemId = "Trends.Ramp (1 min)"
    itemSubscriptionArguments2.GroupParameters.requestedUpdateRate = 1000

    Dim itemSubscriptionArguments3 As New EasyDAItemSubscriptionArguments
    itemSubscriptionArguments3.serverDescriptor.ServerClass = "OPCLabs.KitServer.2"
    itemSubscriptionArguments3.ItemDescriptor.itemId = "Trends.Sine (1 min)"
    itemSubscriptionArguments3.GroupParameters.requestedUpdateRate = 1000

    ' Intentionally specifying an unknown item here, to demonstrate its behavior.
    Dim itemSubscriptionArguments4 As New EasyDAItemSubscriptionArguments
    itemSubscriptionArguments4.serverDescriptor.ServerClass = "OPCLabs.KitServer.2"
    itemSubscriptionArguments4.ItemDescriptor.itemId = "Simulation.Register_I4"
    itemSubscriptionArguments4.GroupParameters.requestedUpdateRate = 1000

    Dim arguments(3) As Variant
    Set arguments(0) = itemSubscriptionArguments1
    Set arguments(1) = itemSubscriptionArguments2
    Set arguments(2) = itemSubscriptionArguments3
    Set arguments(3) = itemSubscriptionArguments4

    ' Instantiate the client object
    Set Client2 = New EasyDAClient

    OutputText = OutputText & "Subscribing item changes..." & vbCrLf
    Dim handleArray() As Variant
    handleArray = Client2.SubscribeMultipleItems(arguments)
    
    OutputText = OutputText & "Processing item changed events for 1 minute..." & vbCrLf
    Pause 60000

    OutputText = OutputText & "Unsubscribing..." & vbCrLf
    Client2.UnsubscribeAllItems

    OutputText = OutputText & "Waiting for 5 seconds..." & vbCrLf
    Pause 5000

    OutputText = OutputText & "Finished." & vbCrLf
    Set Client2 = Nothing
End Sub

Public Sub Client2_ItemChanged(ByVal sender As Variant, ByVal eventArgs As EasyDAItemChangedEventArgs)
    If eventArgs.Succeeded Then
        OutputText = OutputText & eventArgs.arguments.ItemDescriptor.itemId & ": " & eventArgs.vtq & vbCrLf
    Else
        OutputText = OutputText & eventArgs.arguments.ItemDescriptor.itemId & " *** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf
    End If
End Sub
Rem This example shows how to subscribe to changes of multiple items and display the value of the item with each change.
Rem
Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Option Explicit

Dim ItemSubscriptionArguments1: Set ItemSubscriptionArguments1 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments")
ItemSubscriptionArguments1.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2"
ItemSubscriptionArguments1.ItemDescriptor.ItemID = "Simulation.Random"
ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate = 1000

Dim ItemSubscriptionArguments2: Set ItemSubscriptionArguments2 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments")
ItemSubscriptionArguments2.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2"
ItemSubscriptionArguments2.ItemDescriptor.ItemID = "Trends.Ramp (1 min)"
ItemSubscriptionArguments2.GroupParameters.RequestedUpdateRate = 1000

Dim ItemSubscriptionArguments3: Set ItemSubscriptionArguments3 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments")
ItemSubscriptionArguments3.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2"
ItemSubscriptionArguments3.ItemDescriptor.ItemID = "Trends.Sine (1 min)"
ItemSubscriptionArguments3.GroupParameters.RequestedUpdateRate = 1000

Dim ItemSubscriptionArguments4: Set ItemSubscriptionArguments4 = CreateObject("OpcLabs.EasyOpc.DataAccess.OperationModel.EasyDAItemSubscriptionArguments")
ItemSubscriptionArguments4.ServerDescriptor.ServerClass = "OPCLabs.KitServer.2"
ItemSubscriptionArguments4.ItemDescriptor.ItemID = "Simulation.Register_I4"
ItemSubscriptionArguments4.GroupParameters.RequestedUpdateRate = 1000

Dim arguments(3)
Set arguments(0) = ItemSubscriptionArguments1
Set arguments(1) = ItemSubscriptionArguments2
Set arguments(2) = ItemSubscriptionArguments3
Set arguments(3) = ItemSubscriptionArguments4

Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
WScript.ConnectObject Client, "Client_"

Client.SubscribeMultipleItems arguments

WScript.Echo "Processing item changed events for 1 minute..."
WScript.Sleep 60*1000

Sub Client_ItemChanged(Sender, e)
    If Not (e.Succeeded) Then
        WScript.Echo "*** Failure: " & e.ErrorMessageBrief
        Exit Sub
    End If

    WScript.Echo e.Arguments.ItemDescriptor.ItemId & ": " & e.Vtq
End Sub
Requirements

Target Platforms: .NET Framework: Windows 10 (selected versions), Windows 11 (selected versions), Windows Server 2016, Windows Server 2022; .NET: Linux, macOS, Microsoft Windows

See Also