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