我一直在研究一个项目,同时学习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然后我应该如何终止我的线程?每当他们到达该方法的结尾时,它会自动终止吗? –