2011-01-27 6 views
0

私はさまざまな情報のためにサーバーのリストをスキャンするプログラムを開発中です。WaitHandle.WaitAllすべてのスレッドが完了する前に実行されます。 - VB.Net 4.0

スレッドが完了するとエラーが発生する場合を除いて、すべて正常に動作しています。スキャンが完了するかキャンセルボタンによってループが停止しますが、現在のスレッドは続行されます。

私はUIがスキャンが完了したが、progressUpdateが再度実行しようとしているのを見る。 waitallの後にもっと長いthread.sleepを作成することで、この問題を解決できます。

ほとんどの場合、最後のスレッドまで待機しますが、OperationsCompleteがすでに実行されているため、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 

編集私がそれを壊すと、配列は空です。しかし何とか何かがまだ動いている。たぶん私は1つをキャッチしていないです。

答えて

1

.NETの新しいParallel.ForEachメソッドを使用することで、ほぼすべてのコードの複雑さを避けることができます。これにより、WaitHandlesを維持する必要がなくなり、スレッドの最大数を制限する簡単なメカニズムが提供されます。あなたはそう選ぶ。

+0

ありがとう、私はこの回答の電子メールを受け取っていませんでした(チェックボックスをオフにしました)私は新しい方法をもっと調べる必要がありますが、私はそれをチェックします。 – Jasin

+0

最後に、デリゲートとWaitHandlesでこれを使用しました。非常に簡単に私は理解しています。ありがとうございました – Jasin

関連する問題