Pregunta

Estoy trabajando en un programa que escanea una lista de servidores para obtener información diferente.

Todo funciona bien, excepto que a veces recibo errores cuando se realizan los hilos. Ya sea por escaneo completando o el botón Cancelar detenga el bucle, pero permite continuar los hilos actuales.

Veo que la interfaz de usuario dice que el escaneo está completo, pero el progreso supera volver a funcionar. Puedo resolver el problema haciendo un hilo más largo. Duerme después del Waitall.

En su mayor parte, espera al último hilo, pero a veces recibo un error que dice que no puede acceder a la función ProgressUpdate porque OperationsComplete ya se ha ejecutado.

Recibo el error en BackgroundWorker1.eportProgress (_CompletedCount, ScanResult) a continuación, pero no debería llamar eso porque Waitall debería esperar hasta que los subprocesos estén completos.

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

Editar la matriz está vacía cuando la rompe. Pero de alguna manera algo se ejecuta. Tal vez me falta atrapar uno.

¿Fue útil?

Solución

Casi toda la complejidad en su código se puede evitar utilizando el nuevo Paralelo. Método en .NET 4. Esto eliminará la necesidad de mantener WaitHandles, así como ofrecer un mecanismo fácil para limitar el número máximo de subprocesos si así lo desea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top