Frage

Ich arbeite an einem Programm, das eine Liste von Servern nach verschiedenen Informationen scannt.

Alles funktioniert gut, außer manchmal bekomme ich Fehler, wenn die Threads fertig sind. Entweder durch das Abschluss des Scans oder die Schaltfläche Abbrechen, die die Schleife stoppt, aber die aktuellen Threads fortsetzen lassen.

Ich sehe, dass die Benutzeroberfläche besagt, dass der Scan vollständig ist, aber der ProgressUpdate versucht wieder zu laufen. Ich kann das Problem lösen, indem ich einen längeren Thread nach dem Wartall schlafe.

Zum größten Teil wartet es auf den letzten Thread, aber ich erhalte manchmal einen Fehler, der manchmal nicht auf die ProgressUpdate -Funktion zugreifen kann, da OperationsComplete bereits ausgeführt wurde.

Ich erhalte den Fehler bei Hintergrundworker1.ReportProgress (_CompletedCount, ScanResult) unten, sollte jedoch nicht anrufen, da Waitall warten sollte, bis die Threads vollständig sind.

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

Bearbeiten Sie das Array ist leer, wenn ich es breche. Aber irgendwie läuft etwas still. Vielleicht fehlt mir ein.

War es hilfreich?

Lösung

Fast die gesamte Komplexität in Ihrem Code kann durch die Verwendung des Neuen vermieden werden Parallel.foreach Methode in .NET 4. Dadurch wird die Notwendigkeit beseitigt, Wartehandles aufrechtzuerhalten und einen einfachen Mechanismus anzubieten, um die maximale Anzahl von Threads zu begrenzen, wenn Sie dies auswählen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top