Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

run COM interop in separate thread

Status
Not open for further replies.

MickTheBelgian

Programmer
Jan 11, 2001
160
0
0
DK
I have a sub which calls a lot of COM (ActiveX) stuff. If I call the sub from the main thread, it works perfectly. If I call it as a new thread, the whole program just disapears without any kind of error message. If I replace the sub with something more simple, it also works OK. The entire sub does NOT share ANY variables / objects with the main thread. Anybody any idea where I should look at?
 
the "Me.LastBatchNumber..." thingies are shared variables, but even if I comment those lines out, the thing still crashes...

Code:
Private Sub CheckPIM()

        Try
            Dim s As String
            Dim srv As Server
            Dim pt As PIPoint
            Dim inst As New PISDK.PISDKClass
            Dim i As Integer = 0
            Dim dflt As Integer = 0
            Dim d As PISDK.PIData
            Dim v As PISDK.PIValue
            Dim ptAtr As PointAttribute
            Dim numb As New Regex("[0-9]+")
            Dim bName As New Regex("[a-z]+", RegexOptions.IgnoreCase)
            Dim m As Match


            srv = inst.Servers("pika")
            pt = srv.PIPoints("AC240_BatchID")
            d = pt.Data
            v = d.Snapshot
            s = v.Value
            s = s.Trim
            s = s.Replace("--", "")
            Threading.Thread.CurrentThread.Sleep(0)
            If s.Length > 2 And v.IsGood Then
                Me.LastBatchNumber.Total = v.Value
                m = numb.Match(s)
                If m.Success Then
                    Me.LastBatchNumber.Number = m.Value
                End If

                m = bName.Match(s)
                If m.Success Then
                    Me.LastBatchNumber.Letters = m.Value
                End If

            Else
            End If
            pt = srv.PIPoints("AC240_YNT01")
            d = pt.Data
            v = d.Snapshot
            Threading.Thread.CurrentThread.Sleep(0)
            If v.IsGood AndAlso v.TimeStamp.LocalDate.AddMinutes(10) > Now Then
                'data is good
                Me.RTSvalue = v.Value
            Else
                Me.RTSvalue = 0
            End If

            s = s.Trim



        Catch ex As Exception
            Trace.Write("Error while connecting to PIM")
            Trace.WriteLine(ex.Message)
        End Try


    End Sub
 
I switch the ' to switch between main thread and separate thread
Code:
 Private Sub Updatetimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Updatetimer.Tick
        Dim T As Threading.Thread
        Try
            ' Trace.WriteLine("Starting thread")
            Application.DoEvents()
            T = New Threading.Thread(AddressOf CheckPimD)
            T.IsBackground = True
            T.Priority = Threading.ThreadPriority.BelowNormal
            'T.Start()
            Call CheckPIM()
        Catch ex As Exception
            Trace.WriteLine("error while starting new thread:" & ex.Message)
        End Try

    End Sub
 
Interesting. I have run into issues using thread.start in the past, my next suggestion would be to try using delegates.

Code:
Private Del as CheckPIMDelegate

PublicSub RunCheckPIM()
  del = New ProcessDelegate(AddressOf Me.Process)
  Dim cb As New AsyncCallback(AddressOf Me.ProcessComplete)
  del.BeginInvoke(cb, del)
End Sub

Private DelegateSub CheckPIMDelegate()

Private Sub CheckPIMComplete(ByVal ar As IAsyncResult)
  del.EndInvoke(ar)
End Sub

Private Sub CheckPIM()
 '... your code
End Sub

-Rick

----------------------

[monkey] I believe in killer coding ninja monkeys.[monkey]
[banghead]
 
Nope :-( I did find out it only crashes whet it gets called for a second time, so I did a little more effort on the cleaning-up, but that didn't help either...

Code:
Private Sub Updatetimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Updatetimer.Tick
        Dim T As Threading.Thread
        Try
            Del = New CheckPIMDelegate(AddressOf CheckPIM)
            Dim cb As New AsyncCallback(AddressOf Me.CheckPIMComplete)
            Del.BeginInvoke(cb, Del)
        Catch ex As Exception
            Trace.WriteLine("error while starting new thread:" & ex.Message)
        End Try

    End Sub


    Private Sub CheckPIMComplete(ByVal ar As IAsyncResult)
        'gets called when thread complete
        'copy from private to shared to avoid conflict
        Del.EndInvoke(ar)
        Trace.WriteLine("Thread ended")
        Me.LastBatchNumber = Me.tLBN
        Me.RTSvalue = Me.tRTS
    End Sub
    Private Delegate Sub CheckPIMDelegate()

    Private Sub CheckPIM()


        Dim s As String
        Dim srv As Server
        Dim pt As PIPoint
        Dim inst As New PISDK.PISDKClass
        Dim i As Integer = 0
        Dim dflt As Integer = 0
        Dim d As PISDK.PIData
        Dim v As PISDK.PIValue
        Dim ptAtr As PointAttribute
        Dim numb As New Regex("[0-9]+")
        Dim bName As New Regex("[a-z]+", RegexOptions.IgnoreCase)
        Dim m As Match

        Try
            srv = inst.Servers("pika")
            pt = srv.PIPoints("AC240_BatchID")
            d = pt.Data
            v = d.Snapshot
            s = v.Value
            s = s.Trim
            s = s.Replace("--", "")
            Threading.Thread.CurrentThread.Sleep(0)
            If s.Length > 2 And v.IsGood Then
                Me.LastBatchNumber.Total = v.Value
                m = numb.Match(s)
                If m.Success Then
                    Me.tLBN.Number = m.Value
                End If

                m = bName.Match(s)
                If m.Success Then
                    Me.tLBN.Letters = m.Value
                End If

            Else
            End If
            pt = srv.PIPoints("AC240_YNT01")
            d = pt.Data
            v = d.Snapshot
            Threading.Thread.CurrentThread.Sleep(0)
            If v.IsGood AndAlso v.TimeStamp.LocalDate.AddMinutes(10) > Now Then
                'data is good
                Me.tRTS = v.Value
            Else
                Me.tRTS = 0
            End If

            s = s.Trim



        Catch ex As Exception
            Trace.Write("Error while connecting to PIM")
            Trace.WriteLine(ex.Message)
        Finally
            srv.Close()
            srv = Nothing
            d = Nothing
            v = Nothing
            pt = Nothing
        End Try


    End Sub
 
Is "Dim inst As New PISDK.PISDKClass" a COM Object? If so, you should be setting it to nothing it to the finally like the rest of the COM Objects. If it is dieing the second time through the thread it would make me suspicious of the COM objects. When that thread dies the GC should clear it out, but if a COM object is still intact and the second execution happens befor the object is GC'd then there could be an issue.

-Rick

----------------------
[banghead]If you're about to post an ASP.Net question,
please don't do it in the VB.Net forum[banghead]

[monkey] I believe in killer coding ninja monkeys.[monkey]
 
I got it to work! Strangely, the solution was the other way around. I moved declaration of the big classes (server connection) to the main thread, and just call the methods on them in a separate thread. I'll have to test this for long-term stability, but there is light at the end of the tunnel....
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top