Anders
Anders

Reputation: 521

Vb.net using multithreading to go through each listviewitem

I'm pretty new to multithreading, but I am trying to go through each listviewitem where subitem 1 is ".." (quequed).. The code I have right now goes through the first 2, but how can I make it continue with the rest? I am currently running two threads.

I have made this little example application to test out multithreading, which I can then apply to my other application once I get a hang of it.. I pretty much want it to go through each item where status is "..", and then it makes the time go up to 10000 until it continues with the other items, until there are none left.. Any help would be appreciated.

enter image description here

Public Class Form1

Dim i As Integer
Dim i2 As Integer

Dim thread As System.Threading.Thread
Dim thread2 As System.Threading.Thread

Public Class CParameters
    Public Property LID As Integer
End Class

Private Sub startMe(ByVal param As Object)
    Dim p As CParameters = CType(param, CParameters)
    Do Until i = 10000
        i = i + 1
        ListView1.Items(p.LID).SubItems(1).Text = "Running"
        ListView1.Items(p.LID).SubItems(2).Text = i
        If i >= 10000 Then
            ListView1.Items(p.LID).SubItems(1).Text = "OK"
        End If
    Loop
End Sub

Private Sub startMe2(ByVal param As Object)
    Dim p As CParameters = CType(param, CParameters)
    Do Until i = 10000
        i = i + 1
        ListView1.Items(p.LID).SubItems(1).Text = "Running"
        ListView1.Items(p.LID).SubItems(2).Text = i
        If i >= 10000 Then
            ListView1.Items(p.LID).SubItems(1).Text = "OK"
        End If
    Loop
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    thread = New System.Threading.Thread(AddressOf startMe)
    Dim parameters As New CParameters
    parameters.LID = "0"
    thread.Start(parameters)

    'Thread 2
    thread2 = New System.Threading.Thread(AddressOf startMe2)
    parameters = New CParameters
    parameters.LID = "1"
    thread2.Start(parameters)

End Sub

End Class

Upvotes: 0

Views: 426

Answers (1)

trevster344
trevster344

Reputation: 511

If you're using .NET 4.5 I strongly recommend the Task based approach. This approach makes asynchronous programming so much easier. I recreated the form you described with a ListView. I added a 4th column for the counter.

 Public Class CParameters
    Public Property LID As Integer
End Class

Private Async Function startThreadsAsync() As Task

    'WARNING: Await does not create a new thread. Task.run does.
    Await crunchThreadAsync(New CParameters() With {.LID = 0}) 'Create first task
    Await crunchThreadAsync(New CParameters() With {.LID = 1}) 'Create second task
    Await crunchThreadAsync(New CParameters() With {.LID = 2}) 'Create third task

End Function

Private Sub UpdateListItem(ByVal pid As Integer, ByVal Status As String, ByVal Time As String, ByVal Count As String)

    If Not ListView1.InvokeRequired Then 'If on the main ui thread update
        Dim lp As ListViewItem = ListView1.Items(pid)
        lp.SubItems(0).Text = pid.ToString
        lp.SubItems(1).Text = Status
        lp.SubItems(2).Text = Time & "ms"
        lp.SubItems(3).Text = Count
    Else 'If not on the main ui thread invoke the listviews original thread(ui thread)
        ListView1.BeginInvoke(Sub()
                                  Dim lp As ListViewItem = ListView1.Items(pid)
                                  lp.SubItems(0).Text = pid.ToString
                                  lp.SubItems(1).Text = Status
                                  lp.SubItems(2).Text = Time & "ms"
                                  lp.SubItems(3).Text = Count
                              End Sub)
    End If

End Sub

Private Async Function crunchThreadAsync(ByVal param As CParameters) As Task(Of Boolean)
    'Setting start text
    UpdateListItem(param.LID, "Running", "", "0")

    Dim cnt As Integer = 0
    Dim p As CParameters = param
    Dim l As New Stopwatch() 'For displaying total time spent crunching
    l.Start()

    'We're not leaving the UI thread.'

    'Create new thread for crunching
    Dim result As Boolean = Await Task.Run(Function()
                                               Do Until cnt = 10000
                                                   cnt = cnt + 1
                                                   If cnt Mod 1000 = 0 Then
                                                       UpdateListItem(param.LID, "", "", cnt.ToString)
                                                   End If
                                               Loop
                                               Return True
                                           End Function)

    'We're back in the UI thread again.

    l.Stop()

    UpdateListItem(param.LID, "Finished", l.ElapsedMilliseconds.ToString, cnt.ToString)

End Function

Private Async Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    TextBox1.Text &= "Starting crunch." & Environment.NewLine
    Await startThreadsAsync()
    TextBox1.Text &= "Finished crunch." & Environment.NewLine
End Sub

I do not update the ui thread every tick of each counter for a few reasons: The amount of updates on the ui thread would lock up the ui. There is no way around this except to decide when it's necessary to actually update the Ui. In this case I do it every 1000 ticks.

Upvotes: 1

Related Questions