WaitHandle.WaitAll 在所有线程完成之前运行 - VB.Net 4.0
我正在开发一个程序,该程序可以扫描服务器列表以获取不同信息。
一切工作正常,除了有时在线程完成时出现错误。通过扫描完成或取消按钮停止循环但让当前线程继续。
我看到用户界面显示扫描已完成,但 ProgressUpdate 尝试再次运行。 我可以通过在 waitall 之后设置更长的 thread.sleep 来解决问题。
在大多数情况下,它会等待最后一个线程,但有时会出现错误,说它无法访问 ProgressUpdate 函数,因为 OperationsComplete 已经运行。
我在下面的 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
编辑当我破坏数组时它是空的。但不知怎的,有些东西仍然在运行。也许我错过了抓住一个。
I'm working on a program that scans a list of servers for different information.
Everything is working fine except sometimes I get errors when the threads are done. Either by the scan completing or the cancel button stopping the loop but letting the current threads continue.
I see the UI say the scan is complete but the progressUpdate tries to run again.
I can solve the problem by making a longer thread.sleep after the waitall.
For the most part it waits to the last thread but I get an error sometimes saying it can't access the progressUpdate function because OperationsComplete has already been run.
I get the error at BackgroundWorker1.ReportProgress(_completedCount, ScanResult) below but it shouldn't be calling that because WaitAll should wait until the threads are complete.
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
Edit The array is empty when i break it. But somehow something runs still. Maybe I am missing catching one.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通过使用新的 Parallel.ForEach 方法。这将消除维护 WaitHandles 的需要,并提供一种简单的机制来限制最大线程数(如果您愿意)选择。
Nearly all of the complexity in your code can be avoided by using the new Parallel.ForEach method in .Net 4. This will eliminate the need to maintain WaitHandles, as well as offering an easy mechanism to limit the maximum number of threads if you so choose.