vb.net在For..Next循环中具有多个线程的多线程

时间:2015-10-15 16:47:57

标签: vb.net multithreading

大家好我有下面的代码,我想用我所有的处理器内核。最初,sub chekFileDupe中的代码都在SearchForDupes子句中的For..Next循环中,并且在一个线程上工作得很好。我有点卡住创建4个执行checkFileDupe代码的线程,这样我就可以一次检查4个项目,然后等到所有4个线程都完成了。然后继续循环的下一次迭代。

这是原始代码

Private Sub SearchForDupes()

    Me.Refresh()
    Dim totalrecords As Integer = dvSortedSearchResults.Count
    Label1.Text = "Searching for duplicates"
    Label1.Refresh()
    dvSortedSearchResults.Sort = DataSortOrder
    For i = 0 To totalrecords - 6 Step 4
        Dim TrackDifference As Integer
        Dim originalTrack, originalArtist, trackToCompare, artistToCompare As String
        If i / 10 = CInt(i / 10) Then
            Label2.Text = i.ToString + " of " + totalrecords.ToString
            Label2.Refresh()
        End If
        originalArtist = mp3record(i, "Artist")
        originalTrack = mp3record(i, "Track")
        Dim ii As Integer = i + 1
        While ii < totalrecords - 2
            artistToCompare = mp3record(ii, "Artist")
            trackToCompare = mp3record(ii, "Track")
            TrackDifference = Difference(originalTrack, trackToCompare)
            dvSortedSearchResults(ii).Item("Difference") = TrackDifference
            'dgvSearchResults.Rows(ii).Cells("Difference").Value = trackdiff

            If Difference(originalArtist, artistToCompare) < 6 Then
                TrackDifference = Difference(originalTrack, trackToCompare)
                If TrackDifference < 4 Then
                    dvSortedSearchResults(i).Item("Difference") = 999
                    dvSortedSearchResults(ii).Item("Difference") = TrackDifference
                    dvSortedSearchResults(ii).Item("chkdupe") = True
                End If
            Else
                Exit While
            End If
            ii = ii + 1
        End While
    Next
    Label2.Text = ""
    Label1.Text = ""
End Sub

这是多线程的第一次尝试 - 可能是天真的但是嘿 - 每个人都是新的东西

Private Sub SearchForDupes()
        'Dim query = (From record In dvSortedSearchResults Where record.Artist = "Abba" Select record).ToList

        Me.Refresh()
        Dim totalrecords As Integer = dvSortedSearchResults.Count
        Label1.Text = "Searching for duplicates"
        Label1.Refresh()
        dvSortedSearchResults.Sort = DataSortOrder
        Dim params(2) As Integer
        For i = 0 To totalrecords - 6 Step 4
            params(2) = totalrecords
            params(1) = i
            thread1 = New System.Threading.Thread(Sub() checkFileDupe(params))
            thread1.Start()
            params(1) = i + 1
            thread2 = New System.Threading.Thread(Sub() checkFileDupe(params))
            thread2.Start()
            params(1) = i + 2
            thread3 = New System.Threading.Thread(Sub() checkFileDupe(params))
            thread3.Start()
            params(1) = i + 3
            thread4 = New System.Threading.Thread(Sub() checkFileDupe(params))
        Next
        Label2.Text = ""
        Label1.Text = ""
    End Sub

    Private Sub checkFileDupe(params As Array)
        Dim i As Integer = params(1)
        Dim totalrecords As Integer = params(2)
        Dim TrackDifference As Integer
        Dim originalTrack, originalArtist, trackToCompare, artistToCompare As String
        If i / 10 = CInt(i / 10) Then
            Label2.Text = i.ToString + " of " + totalrecords.ToString
            Label2.Refresh()
        End If
        originalArtist = mp3record(i, "Artist")
        originalTrack = mp3record(i, "Track")
        Dim ii As Integer = i + 1
        While ii < totalrecords - 2
            artistToCompare = mp3record(ii, "Artist")
            trackToCompare = mp3record(ii, "Track")
            TrackDifference = Difference(originalTrack, trackToCompare)
            dvSortedSearchResults(ii).Item("Difference") = TrackDifference
            'dgvSearchResults.Rows(ii).Cells("Difference").Value = trackdiff

            If Difference(originalArtist, artistToCompare) < 6 Then
                TrackDifference = Difference(originalTrack, trackToCompare)
                If TrackDifference < 4 Then
                    dvSortedSearchResults(i).Item("Difference") = 999
                    dvSortedSearchResults(ii).Item("Difference") = TrackDifference
                    dvSortedSearchResults(ii).Item("chkdupe") = True
                End If
            ii = ii + 1
        End While
    End Sub     Else
                Exit While
            End If

1 个答案:

答案 0 :(得分:1)

实际上,我建议你做的就是忘记现在的代码并使用BackgroundWorker control。首先创建一个线程来完成工作并启动并运行。优点是后台工作程序允许您将进度报告回主UI线程。应该有很多教程。

我可以尝试解决/指出当前代码中的一些问题,但说实话,它有很多问题。

对于您创建的每个线程,您遇到了使用相同底层对象params(2)的问题,因此当您修改params时,您可以修改所有线程看到的值。您需要做的是每次要将参数传递给新线程时创建一个新数组。 这也是令人困惑的,因为您使用的是闭包Sub () checkFileDupe(params),而不是使用checkFileDupe的正确签名并使用Thread.Start来传递参数。

我建议你创建一个Structure来保存你的主题的参数:

Private Structure FileDupeArguments
    Public StartIndex As Integer
    Public TotalRecords As Integer
End Structure

然后您可以通过以下方式创建新主题:

Dim params As FileDupeArguments
...
thread1 = New System.Threading.Thread(AddressOf checkFileDupe)
params = New FileDupeArguments With {.StartIndex = i, .TotalRecords = totalrecords}
thread1.Start(params)

然后将checkFileDupe声明为:

Sub checkFileDupe(argObj as Object)
    Dim args As FileDupeArguments = CType(argObj, FileDupeArguments)
    Dim i As Integer = args.StartIndex
    Dim totalRecords As Integer = args.TotalRecords
    ...
End Sub

这里的重要部分是您向每个帖子发送一个FileDupeArguments副本。此外,不需要关闭。

从您创建的主题访问控件时出现问题。 例如,

Label2.Text = i.ToString + " of " + totalrecords.ToString
Label2.Refresh()

将不能在后台线程上工作,并会给你错误。我建议你不要从你的工作线程做直接进度报告。就像我提到的那样,BackgroundWorker将允许您使用事件报告进度。

访问dvSortedSearchResults的所有代码都会遇到相同或类似的问题。如果从多个线程访问某些内容,则需要应用锁定。这已经更加先进,超出了这个答案的范围来解释。