我正在开发一个扫描服务器列表以获取不同信息的程序。
一切都运行正常,但有时我会在线程完成时遇到错误。通过扫描完成或取消按钮停止循环但让当前线程继续。
我看到UI说扫描已完成,但progressUpdate尝试再次运行。 我可以通过在waitall之后创建一个更长的thread.sleep来解决问题。
在大多数情况下,它等待到最后一个线程,但我有时会因为操作已完成而无法访问progressUpdate函数而收到错误。
我在下面的BackgroundWorker1.ReportProgress(_completedCount,ScanResult)中收到错误但它不应该调用它,因为WaitAll应该等到线程完成。
Private Sub ScanIsDone(ByVal ar As IAsyncResult)
Dim d As PingDelegate = DirectCast(ar.AsyncState, PingDelegate)
Dim ScanResult As ServerInfo = d.EndInvoke(ar)
SyncLock (_lockObject)
_completedCount = _completedCount + 1
BackgroundWorker1.ReportProgress(_completedCount, ScanResult)
End SyncLock
End Sub
Private Sub BackgroundWorker1_DoWork (ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim servers As List(Of ServerInfo) = DirectCast(e.Argument, List(Of ServerInfo))
Dim waitHandles As New List(Of WaitHandle)
Dim waitHandles2 As New List(Of WaitHandle)
Dim waitHandles3 As New List(Of WaitHandle)
Dim waitHandles4 As New List(Of WaitHandle)
For Each server As ServerInfo In servers
_ThreadsOpen += 1
_WaitCountAll += 1
Dim d As New PingDelegate(AddressOf ScanServer)
Dim ar As IAsyncResult = d.BeginInvoke(server, AddressOf ScanIsDone, d)
Select Case _WaitCountAll
Case 1 To 64
waitHandles.Add(ar.AsyncWaitHandle)
Case 65 To 128
waitHandles2.Add(ar.AsyncWaitHandle)
Case 129 To 192
waitHandles3.Add(ar.AsyncWaitHandle)
Case 193 To 256
waitHandles4.Add(ar.AsyncWaitHandle)
End Select
While _ThreadsOpen > _ThreadMax - 1
Thread.Sleep(200)
End While
If Cancel_Scan = True Then Exit For
Next
If waitHandles.Count <> 0 Then WaitHandle.WaitAll(waitHandles.ToArray())
If waitHandles2.Count <> 0 Then WaitHandle.WaitAll(waitHandles2.ToArray())
If waitHandles3.Count <> 0 Then WaitHandle.WaitAll(waitHandles3.ToArray())
If waitHandles4.Count <> 0 Then WaitHandle.WaitAll(waitHandles4.ToArray())
Thread.Sleep(1000)
End Sub
编辑当我打破它时,该数组为空。但不知何故,某些东西仍在运行也许我错过了抓一个。
答案 0 :(得分:1)
通过在.Net 4中使用新的Parallel.ForEach方法,几乎可以避免代码中的所有复杂性。这将消除维护WaitHandles的需要,并提供一种简单的机制来限制最大数量如果你这样选择的话。