我編寫了一個代碼來搜索文件和文件夾(並檢查插入的單詞的所有可能組合)我有一個可以插入所有字符串的子集。使用多線程或Parallel.ForEach加速搜索文件
我的問題是,我重複每個置換字符串的代碼(對於4個字它意味着24次),我試圖用MultiThreading
來加速代碼。
我已經讀了很多的例子,但我沒能真正理解的原因是多方面的邏輯(一些例子是用C;任何例子是用不同的邏輯寫)
我試着
Parallel.For
Parallel.ForEach
ThreadPool
但我無法在設置列表(包含所有結果)作爲列表框的數據源之前等待所有線程。
我的代碼邏輯是:
通過拆分搜索字符串獲取話
如果搜索類型是「以任意順序全部改爲」然後我得到的所有排列
我開始尋找每個置換字符串
的我不喜歡太多的代碼添加到一個問題,但我認爲這是在這種情況下,要知道我是如何工作的:
Private Sub Btn_Search_Click(sender As Object, e As EventArgs) Handles Btn_Search.Click
Select Case True
Case RBtn_Exact.Checked
StartSearch(Me.TB_Pattern.Text.Trim)
Case RBtn_AllInOrder.Checked
Dim Pattern As String = ""
For Each Word As String In Me.TB_Pattern.Text.Split(New Char() {" "c})
If Word.Trim <> "" Then Pattern &= "*" & Word.Trim
Next
Pattern &= "*"
StartSearch(Pattern)
endsearch()
Case RBtn_AllWithoutOrder.Checked
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
If WordHash.Count > 5 Then
MessageBox.Show("Max 5 words allowed for this kind of search", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
'Get permutations into an array
StringPermutations()
'I need to add "*" at the end of each permutated string
For S As Integer = 0 To PermutationsArr.Length - 1
PermutationsArr(S) &= "*"
Next
'This is for searching without MultiThreading
For Each Pattern As String In PermutationsArr
StartSearch(Pattern)
Next
'This is my last test
'Parallel.ForEach(PermutationsArr,
' Sub(Pattern)
' StartSearch(Pattern)
' End Sub
' )
'Task.WaitAll()
endsearch()
Case RBtn_AnyWord.Checked
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
If WordHash.Count > 5 Then
MessageBox.Show("Max 5 words allowed for this kind of search", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If
For Each Word As String In WordHash
StartSearch(pattern:="*" & Word & "*")
Next
endsearch()
End Select
End Sub
Private Sub StartSearch(ByVal pattern As String)
'Search for files
If Me.CBox_Files.Checked Then
FileSearch(Me.TB_StartFolder.Text, pattern)
End If
'Search for folders
If Me.CBox_Folders.Checked Then
ProcessDir(Me.TB_StartFolder.Text, pattern)
DirSearch(Me.TB_StartFolder.Text, pattern)
End If
End Sub
Sub endsearch()
Me.Btn_Search.Text = "Start"
Me.Btn_Search.BackColor = Me.BackColor
If Me.LB_Files.Items.Count > 0 Then
Me.Lbl_FilesFound.Text = Me.LB_Files.Items.Count.ToString
Me.Lbl_FilesFound.Visible = True
End If
If Me.LB_Folders.Items.Count > 0 Then
Me.Lbl_DirFound.Text = Me.LB_Folders.Items.Count.ToString
Me.Lbl_DirFound.Visible = True
End If
End Sub
Sub DirSearch(ByVal sDir As String, ByVal Pattern As String)
Try
For Each Dir As String In Directory.GetDirectories(sDir)
Try
For Each D As String In Directory.GetDirectories(Dir, Pattern)
Try
If LimitReached(LB_Folders) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_Folders.Checked AndAlso Not LB_Folders.Items.Contains(D) Then LB_Folders.Items.Add(D)
End If
Catch ex As Exception
Continue For
End Try
Next
DirSearch(Dir, Pattern)
Catch ex As Exception
Continue For
End Try
Next
Catch ex As Exception
End Try
End Sub
Sub FileSearch(ByVal sDir As String, ByVal Pattern As String)
Dim d As String = ""
Try
For Each f As String In Directory.GetFiles(sDir, Pattern)
Try
If LimitReached(LB_Files) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_LastModRange.Checked Then
If Me.CBox_Files.Checked AndAlso IntoRangeDate(f) AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
Else
If Me.CBox_Files.Checked AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
End If
End If
Catch ex As Exception
Continue For
End Try
Next
'Search for subfolders
For Each d In Directory.GetDirectories(sDir)
Try
ProcessDir(d, Pattern)
Catch ex As Exception
End Try
Try
FileSearch(d, Pattern)
Catch ex As Exception
End Try
Next
Catch excpt As System.Exception
End Try
End Sub
Private Sub ProcessDir(d As String, ByVal Pattern As String)
Try
For Each f As String In Directory.GetFiles(d, Pattern)
Try
If LimitReached(LB_Files) Then
Me.Lbl_LimitReached.Visible = True
Exit Sub
Else
If Me.CBox_LastModRange.Checked Then
If Me.CBox_Files.Checked AndAlso IntoRangeDate(f) AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
Else
If Me.CBox_Files.Checked AndAlso Not LB_Files.Items.Contains(f) Then LB_Files.Items.Add(f)
End If
End If
Catch ex As Exception
Continue For
End Try
Next
Catch ex As System.Exception
End Try
Try
For Each d In Directory.GetDirectories(d, Pattern)
Try
If Me.CBox_Folders.Checked AndAlso Not LB_Folders.Items.Contains(d) Then LB_Folders.Items.Add(d)
Catch ex As Exception
Continue For
End Try
Next
Catch ex As Exception
End Try
End Sub
編輯
下面我爲獲得置換(我知道它有一個特定的邏輯,但它的工作原理,它似乎不夠快)代碼:
Private Sub StringPermutations()
Try
Dim WordHash As New HashSet(Of String)
For Each Word As String In Split(Me.TB_Pattern.Text, " ")
If Word.Trim <> "" Then WordHash.Add(Word.Trim)
Next
Dim WordList As List(Of String) = WordHash.ToList
ReDim PermutationsArr(Factorial(WordList.Count) - 1)
AddString(WordList, 0)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Function Factorial(ByVal Num As Integer) As Integer
Try
If Num > 0 AndAlso Num < 12 Then
Dim Result As Int32 = 1
Do
Result *= Num
Num -= 1
Loop Until Num <= 1
Return Result
Else
Return 0
End If
Catch ex As Exception
Return Nothing
End Try
End Function
Private Sub AddString(ByVal WordList As List(Of String), ByVal StartId As Integer)
Try
Dim InsLoop As Integer = Factorial(WordList.Count - 1)
If InsLoop = 0 Then InsLoop = 1
For Each Word As String In WordList
For InsWord As Integer = 1 To InsLoop
PermutationsArr(StartId + InsWord - 1) &= "*" & Word
Next
If WordList.Count > 1 Then
Dim Remaining As New List(Of String)
For Each RemWord As String In WordList
If RemWord <> Word Then Remaining.Add(RemWord)
Next
AddString(Remaining, StartId)
End If
StartId += InsLoop
Next
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
你也許可以簡化事情極大地 - 也許是爲了使用LINQ的不需要並行處理的點。如果測試一個文件是否匹配的邏輯被隔離在子上,像這樣的東西可能會工作:'Dim files = Directory.EnumerateFiles(startpath,「*。*」,SearchOption.AllDirectories).Where(Function(w)FileMatches W))。ToArray'。其中'FileMatches()'是一種測試條件是否適用的方法。如果一個條件是文件擴展名,請在'EnumerateFiles'調用中進行設置,以便NET爲您篩選它們。 – Plutonix
@Plutonix我會測試你的建議。無論如何,我已經嘗試了沒有遞歸的代碼,但我的嘗試並沒有返回所有文件 – genespos
很難辨別出你在代碼中處理的所有規則和條件,所以你最終可能會在不同的文件夾上運行類似的東西,合併結果。它似乎可以簡化,但... – Plutonix