Search code examples
vb.netmultiprocessing

Picking values twice with multithread [VB.NET]


I'm trying to apply some multithreading to my codes, therefore I was trying to practice with some easy tasks. In the following simple code I want every thread to take one value of a counter (m), then increase its value, and then make something using the value previously taken and copy the result of it in a list (listL).. Unfortunately I can't prevent the thread to take the same value twice... It's probably trivial but I can't find a proper solution... Thanks in advance..

Mario

imports System.Threading

Module Module1
    Public m As UShort = 0
    Dim listL As New List(Of Integer)

Sub Main()
    Dim t1 As New Thread(AddressOf TestMultiThreading)
    Dim t2 As New Thread(AddressOf TestMultiThreading)

    t1.Start("a")
    t2.Start("b")

    t1.Join()
    t2.Join()

    For m As Integer = 0 To listL.Count - 1
        For n As Integer = m + 1 To listL.Count - 1
            If listL(n) = listL(m) Then Debug.Print("same {0} {1}", n, m)
        Next n
    Next m

    listL.Clear()

End Sub

Public Sub TestMultiThreading(ByVal X As Char)
    Dim lobj1 As New Object
    Dim p As Integer

    Do While m < 100
        SyncLock lobj1
            p = m
            m += 1
        End SyncLock
        ' various calculations ...
        ' eventually
        listL.Add(m)
    Loop

    lobj1 = Nothing

    Debug.WriteLine("end " & X)

End Sub

End Module

Solution

  • I created this test. Take a look at the differences, especially how the lock object is outside the loop, and the value p is added to the list, not m.

    Module Module1
    Public m As Integer = 0
    Dim listL As New List(Of String)
    
    Sub Main()
        Dim t1 As New Threading.Thread(AddressOf TestMultiThreading)
        Dim t2 As New Threading.Thread(AddressOf TestMultiThreading)
    
        t1.Start("a")
        t2.Start("b")
        Threading.Thread.Sleep(0)
        t1.Join()
        t2.Join()
    
        For xm As Integer = 0 To listL.Count - 1
            Debug.WriteLine(listL(xm))
            For n As Integer = xm + 1 To listL.Count - 1
                If listL(n) = listL(xm) Then
                    Debug.Print("same {0} {1}", n, xm)
                End If
            Next n
        Next xm
    
        listL.Clear()
        Stop
    End Sub
    
    Dim lobj1 As New Object
    
    Public Sub TestMultiThreading(ByVal X As Object)
    
        Dim p As Integer
        Dim c As String = DirectCast(X, String)
        Do While m < 100
            SyncLock lobj1
                p = m
                m += 1
            End SyncLock
            Threading.Thread.Sleep(0) ' various calculations ...
            ' eventually
            'listL.Add(p.ToString & c) 'for debug
            listL.Add(p.ToString)
        Loop
    
    
        Debug.WriteLine("end " & c)
    
    End Sub
    
    End Module