0

I have code that sends a ping to a batch of computers, and opens a VNC session to any that respond that they are online.

The pings are sent in a parallel.foreach loop, and an event is raised when a reply is receieved.

Despite putting a synclock block around the AddHost code, it is still being entered by multiple threads simultaneously.

I think it has something to do with the code being called by a raiseevent on another object.

This is the method that is handling the event

Private Sub AddHost(hostname As String)
    ' panesList is an list(of RemoteDesktop) prepopulated with  36 individual RemoteDesktop objects
    Dim vnc As RemoteDesktop = panesList(Position)
    vnc.GetPassword = New AuthenticateDelegate(Function() vncPassword)
    SyncLock Semaphore
        Try
            If Position = 36 Then
                Return
            End If

            vnc.Connect(hostname, 0, True, True)
            Position += 1

        Catch ex As Exception

        End Try
    End SyncLock

End Sub


Private Sub HandleConnect(hostFilter As String)
    AddHandler OnlineFinder.LiveComputer, AddressOf AddHost
    Dim bg As New Task(Sub() OnlineFinder.CheckFilteredASync(hostFilter))
    bg.Start()
    ' AddHandler OnlineFinder.SearchComplete, AddressOf Finished
End Sub

From the object OnlineFinder.vb

    Public Sub CheckFilteredASync(filterString As String)
    Dim Ctable As DataTable = CTableAdapter.GetDataByPartName($"{filterString}%")
    Dim clist As New List(Of String)
    For Each drow As DataRow In Ctable.Rows
        clist.Add(drow.Field(Of String)("Name"))
    Next
    Searching = True
    Dim parallelLoopResult = Parallel.ForEach(clist, Sub(site) Ping(site))
    RaiseEvent SearchComplete()
End Sub

    Private Sub Ping(host As String)
    If ValidPing(host) Then
        RaiseEvent LiveComputer(host)
    End If
End Sub

How should I be doing this so only one event is processed at a time (but it doesn't hang the UI)

Peter Page
  • 97
  • 3
  • 12
  • Two `SyncLock` statements or two instances of the same statement must lock on the same object in order to work as a unit. Are you sure that that `Semaphore` variable is referring to the same object regardless of the thread the method is called on? – jmcilhinney Jun 17 '21 at 14:43
  • I defined Semaphore at the top of the class (not OnlineFinder.vb, which is a module) as Dim Semaphore as new Object The top block of code is Monitor.vb a forms class. The bottom block is OnlineFinder.vb a module. – Peter Page Jun 17 '21 at 19:19
  • The lock object `Semaphore` might need to be `Shared`, if it could be called from multiple instances and you want to constrain that. Note that it's only the lock block that is constrained from being entered twice, the routine as a whole can be entered, and execution will wait at the `SyncLock` statement. – Craig Jun 17 '21 at 20:20
  • I've made the Semaphore object shared, and it hasn't stopped the issue. When I run the debugger I can see multiple threads all entering the synclock block before the previous has left. – Peter Page Jun 18 '21 at 08:24

0 Answers0