# VBForums CodeBank > CodeBank - Visual Basic .NET >  Passing Data to a Thread Entry Method

## jmcilhinney

C# version here.

Originally there was no way to pass data directly to a method that you were using as the entry point for a thread.  You had to assign your data to one or more member variables and then retrieve it again in the new thread.
vb.net Code:
Private data As Integer Private Sub InitiateThread()    Me.data = 100     Dim t As New Thread(AddressOf DoWork)     t.Start()End Sub Private Sub DoWork()    Dim data As Integer = Me.data     'Use data here.End Sub
Many developers would create classes specifically for the new thread that incorporated the data, which was assigned to properties, and the thread entry point.
vb.net Code:
Private Class Worker     Private _data As Integer     Public WriteOnly Property Data() As Integer        Set(ByVal value As Integer)            Me._data = value        End Set    End Property     Public Sub DoWork()        Dim data As Integer = Me._data         'Use data here.    End Sub End Class  Private Sub InitiateThread()    Dim w As New Worker     w.Data = 100     Dim t As New Thread(AddressOf w.DoWork)     t.Start()End Sub
With .NET 2.0 came the ParameterizedThreadStart delegate and the ability to pass a single object to the entry method via the Thread.Start method.
vb.net Code:
Private Sub InitiateThread()    Dim t As New Thread(AddressOf DoWork)     t.Start(100)End Sub Private Sub DoWork(ByVal obj As Object)    Dim data As Integer = CInt(obj)     'Use data here.End Sub
Now, with VB 2008, we have a new way, thanks to Lambda Expressions.  This is easier and neater than the old ways and overcomes the weak typing required by the ParameterizedThreadStart delegate.  With this new approach you can write a function that takes as many arguments as you like of whatever type you like.  You then create a ThreadStart delegate using a Lambda Expression that calls this function, e.g.
vb.net Code:
Private Sub InitiateThread()    Dim t As New Thread(DirectCast(Function() DoWork(100), ThreadStart))     t.Start()End Sub Private Function DoWork(ByVal data As Integer) As Object    'Use data here.     Return NothingEnd Function
The only real drawback with this approach is that your work method MUST be a function, even though the return value cannot be used anywhere.  When VB 2010 arrives that will no longer be the case because Lambda Expressions will be able to be Subs as well as Functions.

I have to admit that I don't really understand how a cast from a Lambda Expression that's a function to type ThreadStart, which has no return type, is legal but it seems to work so I'm happy to use it.

----------


## jmcilhinney

VB 2010 has added support for action lambdas to the existing value lambdas, i.e. you can now create a lambda expression using the Sub keyword as well as the Function keyword.  As such, the issue with the last code snippet in post #1 is removed in VB 2010:
vb.net Code:
Private Sub InitiateThread()    Dim t As New Thread(DirectCast(Sub() DoWork(100), ThreadStart))     t.Start()End Sub Private Sub DoWork(ByVal data As Integer)    'Use data here.End Sub

----------


## coolcurrent4u

hello thanks jmcilhinney for this brief,

in the class approach of this threading, will this method avoid data overwriting (race condition) since the same DoWork will be used by multiple threads
since you say


vb Code:
Private Sub InitiateThread()
    Dim w As New Worker
 
    w.Data = 100
 
    Dim t As New Thread(AddressOf w.DoWork)
 
    t.Start()
End Sub

----------


## jmcilhinney

> hello thanks jmcilhinney for this brief,
> 
> in the class approach of this threading, will this method avoid data overwriting (race condition) since the same DoWork will be used by multiple threads
> since you say
> 
> 
> vb Code:
> Private Sub InitiateThread()
    Dim w As New Worker
 
    w.Data = 100
 
    Dim t As New Thread(AddressOf w.DoWork)
 
    t.Start()
End Sub


But it's not the same DoWork method.  You're creating a new Worker object each time and each of those objects has its own Data property and DoWork method.  It would only be if you used the same Worker object each time or Worker was a module or a class with Shared members that you would experience interference between threads.

----------


## coolcurrent4u

Hello John

Am getting race condition with this implementation. in the listview, one item is usually listed more than once, which is not suppose to be so. The my code

I wanted to use the class implementation, but how do i get the clas to return values so i can display it in list view just like thsi one


vb Code:
Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnStart.Click
        ListItemsToProcess.AddRange(TextBox1.Lines)
        count = 0
        StartProcess()
    End Sub
     Private Sub StartProcess()
        Me.btnStart.Enabled = False
        ' start the first five threads
        For i = 0 To intMaxThreadCount - 1
            If intNextItemIndex < ListItemsToProcess.Count Then
                Threading.Thread.Sleep(100)
                StartNextItem(i)
            End If
        Next
        ' update running threads
    End Sub
     Private Sub StartNextItem(ByVal index As Integer)
        If index < ListItemsToProcess.Count Then
            ' start parsing thread
            Dim t As New Thread(AddressOf DoWork)
            t.Name = "Thread " & index
            t.Start(index)
            intNextItemIndex += 1
        End If
    End Sub
     Private Sub DoWork(ByVal data As Object)
        Dim index As Integer = CInt(data)
        Dim sTemp As String = Nothing
        Dim objLock As Object = New Object()
        Dim t As Double = 0
        myWatch = New Stopwatch
        Try
            ' Proces item
            myWatch.Start()
            SyncLock (objLock)
                sTemp = ProcessData(ListItemsToProcess(index).ToString)
                'sTemp = CountTo().ToString
            End SyncLock
            myWatch.Stop()
            t = myWatch.ElapsedMilliseconds / 1000
        Catch ex As Exception
            ' catch error
            sTemp = ex.Message
            Debug.Print(sTemp)
        End Try
        Debug.Print(index.ToString)
        'AddItem(index, sTemp)
        AddItem(index, t.ToString)
        StartNextItem(intNextItemIndex)
    End Sub
     Public Delegate Sub AddItemDelegate(ByVal index As Integer, ByVal item As String)
     Public Sub AddItem(ByVal index As Integer, ByVal item As String)
        Dim objLock As Object = New Object()
        If Me.InvokeRequired Then
            Me.Invoke(New AddItemDelegate(AddressOf AddItem), index, item)
        Else
            Dim lvItem As New ListViewItem
            With lvItem
                .Text = index.ToString
                .SubItems.Add(ListItemsToProcess(index).ToString)
                If item.Length < 51 Then
                    .SubItems.Add(item.ToString)
                Else
                    .SubItems.Add(item.Length.ToString)
                End If
             End With
            count = Interlocked.Increment(count)
            tspbStatus.Value = CInt((count / ListItemsToProcess.Count) * 100)
            SyncLock (objLock)
                listView1.Items.Add(lvItem)
            End SyncLock
         End If
     End Sub

----------


## ident

Hi john, would it be rude to ask a quick question on thread termination here? I dont really feel it needs it's own thread.

----------


## jmcilhinney

> Hi john, would it be rude to ask a quick question on thread termination here? I dont really feel it needs it's own thread.


The thread title says "Passing Data to a Thread Entry Method".  Is your question about that?  It would appear not, so it doesn;t belong in this thread.

----------

