You seem to be correct.
After swapping the very first line of these 2 functions and making small changes at the end of each function, the address reading appears to be working fine.
Here are the new functions so you could check whether those small changes at the end were correct (they do work):
Public Function BeginRead(ByVal startAddress As String, ByVal numberOfElements As Integer) As Integer Implements IComComponent.BeginRead
If DLL Is Nothing Then CreateDLLInstance()
'*********************************************************************
'* If Async Mode, then return immediately and return value on event
'*********************************************************************
If TransactionID < 32767 Then
TransactionID += 1
Else
TransactionID = 0
End If
If ReadSubscriptionState Is Nothing Then
ReadSubscriptionState = New Opc.Da.SubscriptionState
ReadSubscriptionState.Name = "AsyncReadGroup"
ReadSubscription = DLL.CreateSubscription(ReadSubscriptionState)
End If
Dim Items(0) As Opc.Da.Item
Items(0) = New Opc.Da.Item
If (m_OPCTopic IsNot Nothing) AndAlso (String.Compare(m_OPCTopic, "") <> 0) Then
Items(0).ItemName = "[" & m_OPCTopic & "]"
Else
Items(0).ItemName = ""
End If
Items(0).ItemName &= startAddress
If numberOfElements > 1 Then
Items(0).ItemName &= ",L" & numberOfElements
End If
Items(0).SamplingRate = 250
Items(0).ClientHandle = TransactionID
Dim ItemRes() As Opc.Da.ItemResult
ItemRes = ReadSubscription.AddItems(Items)
For i As Integer = 0 To ItemRes.Length - 1
Items(i).ServerHandle = ItemRes(i).ServerHandle
Next
Dim req As Opc.IRequest = Nothing
ReadSubscription.Read(Items, TransactionID, New Opc.Da.ReadCompleteEventHandler(AddressOf AsyncReadCompleteCallback), req)
'Dim r() As String = {TransactionID.ToString}
'Return r
Return TransactionID
End Function
Public Function Read(ByVal startAddress As String, ByVal numberOfElements As Integer) As String() Implements IComComponent.Read
If DLL Is Nothing Then CreateDLLInstance()
Dim items(0) As Opc.Da.Item
items(0) = New Opc.Da.Item
If m_OPCTopic IsNot Nothing AndAlso (String.Compare(OPCTopic, "") <> 0) Then
items(0).ItemName = "[" & m_OPCTopic & "]"
Else
items(0).ItemName = ""
End If
items(0).ItemName &= startAddress
If numberOfElements > 1 Then
items(0).ItemName &= ",L" & numberOfElements
End If
items(0).SamplingRate = 50
items(0).Active = True
Dim values() As Opc.Da.ItemValue
values = DLL.Read(items)
Dim ArraySize As Integer = 0
If TypeOf (values(0).Value) Is System.Array Then
ArraySize = DirectCast(values(0).Value, System.Array).Length - 1
End If
Dim ReturnValues(ArraySize) As String
If ArraySize > 0 Then
For i As Integer = 0 To DirectCast(values(0).Value, System.Array).Length - 1
ReturnValues(i) = Convert.ToString(values(0).Value)
Next
Else
ReturnValues(0) = Convert.ToString(values(0).Value)
End If
'Return Convert.ToInt32(values(0).Value)
Return ReturnValues
End Function