我一直在研究一個項目,同時學習vb.net:一個多線程代理檢查器。我有它的工作,並在小測試(列表1000代理檢查)它工作得很好。但是,我想用它來檢查500,000或更多的代理列表。當我嘗試這樣做時,我看到了大量的CPU使用情況。我有一個帶有16GB內存的AMD FX-8320,僅供參考。需要幫助減少多線程VB.net程序的CPU使用率
我的所有代碼都可以在我的Github上查看(click this to visit),但我會在這裏複製主要的重要部分。
基本流程:
- 用戶點擊「開始」,並且每個線程啓動上 「threadedProxyChecker()」
- threadedProxyChecker()通過列表(串)的所有成員進行迭代包含所有代理從文本文件加載
- 由每個線程正在測試的代理被加載到一個臨時List(Of String)中,所以工作不會進行兩次,並且此List(Of String)受SyncLock保護。調用「checkProxy(proxy)」,然後將代理從臨時List(Of String)中刪除。
- 結果記錄到l1工作或l2失敗。 (可能不需要l2,只是一個存儲在int中的所有失敗數的計數?)
- 「performStep()」更新UI以顯示ListBox中的工作代理,增加ProgressBar並報告完成百分比作爲標籤中工作/不響應的計數。
- 當每個線程到達列表末尾時,工作/無響應代理的總數與列表大小進行比較,作爲程序結束的條件。
:所有工作完成後(我知道這是不好的,但我不知道我還能怎麼做)Function checkProxy(proxy As String) As Boolean Dim myProxy As WebProxy Dim Temp As String Try myProxy = New WebProxy(proxy) Dim r As HttpWebRequest = HttpWebRequest.Create("http://azenv.net") r.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36" r.Timeout = 3000 r.Proxy = myProxy Dim re As HttpWebResponse = r.GetResponse() Dim rs As Stream = re.GetResponseStream Using sr As New StreamReader(rs) Temp = sr.ReadToEnd() End Using Dim Text = Temp rs.Dispose() rs.Close() r.Abort() If Text.Contains("HTTP_HOST = azenv.net") Then If Text.Contains("REQUEST_TIME =") Then Return True End If Else Return False End If Catch ex As Exception Return False End Try Return False End Function
我如何檢查每個代理Thread.Abort的()被調用
每個線程執行的主要代碼:
Private Sub threadedProxyChecker()
Dim counter As Integer = 0
For Each proxy As String In proxies
SyncLock curProxLock
If tmpProx.Contains(proxy) Then
GoTo Skip
Else
tmpProx.Add(proxy)
End If
End SyncLock
If Not l2.Contains(proxy) Then
If Not l1.Contains(proxy) Then
If (checkProxy(proxy)) Then
performStep(True, proxy)
l1.Add(proxy)
SyncLock curProxLock
tmpProx.Remove(proxy)
End SyncLock
Else
performStep(False, proxy)
l2.Add(proxy)
SyncLock curProxLock
tmpProx.Remove(proxy)
End SyncLock
End If
End If
End If
Skip:
Next
If proxies.Count() <= (l1.Count() + l2.Count()) Then
If Not isBox Then
SyncLock indexLock
MessageBox.Show("Done checking!" & vbNewLine & l1.Count() & " working proxies")
isBox = True
End SyncLock
Label5.Invoke(Sub()
Label5.Text = "Working: " & l1.Count()
Label5.Update()
End Sub)
Label4.Invoke(Sub()
Label4.Text = "Unresponsive: " & l2.Count()
Label4.Update()
End Sub)
End If
End If
Thread.CurrentThread.Abort()
End Sub
如何線程啓動:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
isBox = False
Dim threadCount As Integer = TrackBar1.Value
For int As Integer = 1 To threadCount Step 1
d(int.ToString) = New Thread(AddressOf threadedProxyChecker)
d(int.ToString).IsBackground = True
d(int.ToString).Start()
Next
End Sub
的「performStep()」方法,通過「threadedProxyChecker()」之稱
Function performStep(bool As Boolean, proxy As String)
If bool Then
ListBox2.Invoke(Sub()
ListBox2.Items.Add(proxy)
ListBox2.TopIndex = ListBox2.Items.Count - 1
ListBox2.Update()
Label5.Text = "Working: " & l1.Count()
Label5.Update()
End Sub)
Else
Label4.Invoke(Sub()
Label4.Text = "Unresponsive: " & l2.Count()
Label4.Update()
End Sub)
End If
count = count + 1
ProgressBar1.Invoke(Sub()
ProgressBar1.PerformStep()
ProgressBar1.Update()
End Sub)
Label1.Invoke(Sub()
Dim percent As Double = Math.Round((count/proxies.Count() * 100), 2, MidpointRounding.AwayFromZero)
Label1.Text = "Progress: " & count & "/" & proxies.Count() & " checked " & "(" & percent & "%)"
Label1.Update()
End Sub)
Return True
End Function
如何使事情更順利地進行任何意見和/或如何降低CPU佔用率將真棒!謝謝:) -Eric
永遠不要調用'Thread.CurrentThread.Abort()' - 只有**異常是因爲如果你試圖崩潰你的程序並且你想要結束所有的線程。調用'.Abort()'可能會破壞.NET運行時狀態,並且不能依賴它在之後正確運行。 – Enigmativity
還有一個很好的機會,就是你用所有的'.Invoke'調用來殺死你的CPU。你想盡可能避免它們。您應該從UI線程中整理數據,並在後臺線程上整理進程,然後將數據編組回到UI線程一次。 – Enigmativity
@Enigmativity然後我應該如何終止我的線程?每當他們到達該方法的結尾時,它會自動終止嗎? –