2015-10-15 226 views
-1

嗨伙计我有下面的代码,我想使用我所有的处理器核心。最初,sub chekFileDupe中的代码全部位于SearchForDupes子目录中的For..Next循环内,并且在一个线程上工作得很好。我有点卡住创建4个执行checkFileDupe代码的线程,这样我就可以一次检查4个项目,然后等待所有4个线程完成。然后继续循环的下一次迭代。vb.net多线程与For..Next循环中的多线程

这是原来的代码

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 
+0

您总共开始了'(totalrecords-6)/ 4 * 4'个线程,即每For迭代循环有4个新线程。这是你的意图吗? – MicroVirus

+0

hehe - 哎呀 - 不。创建4个线程并在下一次迭代之前销毁它们,我猜 - 这可能效率很低 –

+0

您在线程之间划分工作的方式不正确。你需要考虑如何将检查每个元素的任务与每个其他元素分开。 – MicroVirus

回答

1

其实,我可能会建议你做的是忘记你现在的代码并使用BackgroundWorker control。从创建一个线程开始,完成工作并启动并运行。好处是后台工作人员可以让您将进度报告回主UI线程。那里应该有很多教程。


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


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

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

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

然后宣布checkFileDupe为:

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

然后,你可以通过创建一个新的线程:

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

+0

请注意,我的VB.NET有点生疏,所以有可能我在代码片段中犯了一个小错误。请告诉我。 – MicroVirus

+1

@DavidWilson我已经更新了我的答案。我建议你从一个使用后台工作者控制的线程开始。先把它弄好,然后运行。当前的代码有太多的问题需要解决。 – MicroVirus

+0

谢谢 - 是的,这是凌乱的代码。我写了很久以前,我学到了更多 - 也许我应该排序原始代码第一:)作为一个最后的事情的时刻..我需要以某种方式在每次迭代结束时销毁线程或做他们被摧毁(我想也许)他们超出范围循环迭代? –