Waithandle.Waitallは、すべてのスレッドが完了する前に実行されます-VB.NET 4.0

StackOverflow https://stackoverflow.com/questions/4812301

  •  25-10-2019
  •  | 
  •  

質問

さまざまな情報に対してサーバーのリストをスキャンするプログラムに取り組んでいます。

スレッドが完了したときにエラーが発生する場合を除き、すべてが正常に機能しています。スキャンが完了するか、キャンセルボタンがループを停止するが、現在のスレッドを続行することにより。

UIはスキャンが完了したと言っていますが、ProgressUpdateは再び実行しようとします。より長いスレッドを作ることで問題を解決することができます。

ほとんどの場合、最後のスレッドまで待っていますが、OperationsCompleteがすでに実行されているため、ProgressUpDate関数にアクセスできないというエラーが発生します。

BackgroundWorker1.ReportProgress(_completedCount、scanresult)でエラーが発生しますが、スレッドが完了するまで待機する必要があるため、それを呼び出すべきではありません。

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

編集アレイは私が壊すときに空です。しかし、どういうわけか何かがまだ実行されます。たぶん私はそれを捕まえるのが見逃しています。

役に立ちましたか?

解決

コードのほぼすべての複雑さは、新しいものを使用することで回避できます Parallech.Foreach .NET 4のメソッドにより、ウェイトハンドルを維持する必要性がなくなり、選択した場合に最大数のスレッドを制限する簡単なメカニズムを提供します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top