Gregor

PIAsynchStatus example in VB.Net

Blog Post created by Gregor on Aug 27, 2012

When joining the vCampus team 2 weeks, I was looking for something simple to refresh my programming skills. It turned out that porting the PIAsynchStatus Example (see pisdk.chm) from VB6 to VB.Net was challenging enough. I believe the result is a good example for asynchronous PI Data Access. So please allow me using it for my first blog post even there will be nothing new for most of you.

 

 8637.Form2.jpg

 

The original example is using a Timer to check for status changes from time to time each 0.5 seconds). The advantage is that this allows checking the progress but my idea was using asynchronous callback instead of the Timer. So I have removed the timer and changed the definition of the routine that is called by the Timer in the original VB 6 example to make it handled (triggered) by the OnStatusChange event fired by the asynchronous GetPoints() call:

 

 

 
    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants)

 =>

 
    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants) Handles asynchevents.OnStatusChange

Updating a ProgressBar with OnProgressChange() event gave me an issue. The first OnProgressChange() was with 1% and the second with 10%. Afterwards my little application was hanging even after disabling the handler for OnStatusChange(). If you’ve managed using OnProgressChange() succesfully, please let me know how. I decided removing the ProgressBar for now.

 

The next issue I ran into is the following error when attempting to update a control on Form1 from within asynchevents_OnStatusChange():

 

 

 

InvalidOperationException was unhandled by user code: Cross-thread operation is not valid …

 

 

 

The callback from the asynchronous function call is handled in an additional thread that does not have access to the controls that are handled with the main application thread.

 

The solution is delegating control updates to a separate sub and invoking methods if needed. The OnStatusChange() sub handles different statuses and delegates control updates to separate subs:

 
    Private Sub asynchevents_OnStatusChange(ByVal NewStatus As CallStatusConstants) Handles asynchevents.OnStatusChange
        Select Case asynchevents.Status
            Case Is = csInProgress
                ShowInProgress()
            Case Is = csComplete
                ShowComplete()
            Case Is = csCancelComplete
                ShowCancel()
            Case Else
                ShowElse()
        End Select
    End Sub

Let's have a look at ShowInProgress() and the conditional invoke. 

 
    Private Sub ShowInProgress()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf ShowInProgress))
        Else
            Try
                lbStatus.Items.Add("New Status: ... in progress")
            Catch ex As Exception
                lbStatus.Items.Add("ShowProgress: " & ex.Message)
            End Try
        End If
    End Sub

The complete Visual Studio .NET 2010 project is attached to this post. I am excited about your replies espacially about your suggestions for improvements.

 

Last but not least I like to discuss the where clause that is passed with the GetPoints() call. This is a powerful way searching tags by its attributes. Please review the following examples.

 

1. Non-case sensitive search for all tags that have a specific character or a sequence of characters at first place of their name:

 

tag='S*' 
tag='SIN*'
tag='SINUS??D'

2. Search for tags that have a specific point source and a specific Location1 value. This query is very useful when one would retrieve all the tags serviced by a specific interface instance:

pointsource='OPC' AND Location1=1

3. Query for all tags having a specific pointtype assigned:

pointtype='Int32'

Attachments

Outcomes