Domanda

Sto lavorando su un programma che analizza un elenco di server per informazioni diverse.

Tutto sta funzionando benissimo tranne a volte ricevo errori quando i fili sono fatte. Sia per la scansione completando o il pulsante Annulla l'arresto del ciclo, ma lasciando i fili di corrente continua.

vedo l'interfaccia utente dire la scansione è completata, ma il progressUpdate tenta di eseguire di nuovo. Posso risolvere il problema facendo una Thread.sleep più a lungo dopo l'WaitAll.

Per la maggior parte si aspetta fino all'ultimo filo ma ottengo un errore a volte dicendo che non è possibile accedere alla funzione progressUpdate perché OperationsComplete è già stato eseguito.

ottengo l'errore al BackgroundWorker1.ReportProgress (_completedCount, ScanResult) al di sotto, ma non dovrebbe essere chiamata che a causa WaitAll dovrebbe attendere che i fili siano completi.

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

Modifica L'array è vuoto quando i romperlo. Ma in qualche modo qualcosa corre ancora. Forse mi manca la cattura di uno.

È stato utile?

Soluzione

Quasi tutta la complessità nel codice può essere evitato utilizzando la nuova metodo Parallel.ForEach Net 4. Ciò elimina la necessità di mantenere WaitHandles, oltre ad offrire un meccanismo semplice per limitare il numero massimo di thread se lo si vuole.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top