2009-03-11 19 views
8

Los usuarios de mi aplicación escriben HTML en un control TextBox.¿Cómo puedo cancelar y reiniciar correctamente un proceso de BackgroundWorker?

Quiero que mi aplicación valide su entrada en segundo plano.

Como no deseo mejorar el servicio de validación, he intentado generar un retraso de un segundo antes de cada validación.

Sin embargo, parece que no puedo interrumpir correctamente un proceso de BackgroundWorker que ya se está ejecutando.

Mi código de Visual Basic:

 
Sub W3CValidate(ByVal WholeDocumentText As String) 

    'stop any already-running validation 
    If ValidationWorker.IsBusy Then 
     ValidationWorker.CancelAsync() 
     'wait for it to become ready 
     While ValidationWorker.IsBusy 
      'pause for one-hundredth of a second 
      System.Threading.Thread.Sleep(New TimeSpan(0, 0, 0, 0, 10)) 
     End While 
    End If 

    'start validation 
    Dim ValidationArgument As W3CValidator = New W3CValidator(WholeDocumentText) 
    ValidationWorker.RunWorkerAsync(ValidationArgument) 

End Sub 

Parece que después de llamar CancelAsync de mi BackgroundWorker(), su IsBusy nunca llega a ser falsa. Se queda atascado en un ciclo infinito.

¿Qué estoy haciendo mal?

+0

me refiero a salir del procedimiento si e.Cancelled es cierto. – Pat

Respuesta

0

he encontrado la respuesta en este artículo:

BackgroundWorker Closure and Overridable Task por Patrick Smacchia

me he adaptado a su código:

 
Private _ValidationArgument As W3CValidator 

Sub W3CValidate(ByVal WholeDocumentText As String) 
    If _ValidationArgument IsNot Nothing Then 
     _ValidationArgument = New W3CValidator(WholeDocumentText) 
     Exit Sub 
    End If 
    If Not ValidationWorker.IsBusy Then 
     ValidationWorker.RunWorkerAsync(New W3CValidator(WholeDocumentText)) 
     Exit Sub 
    End If 
    _ValidationArgument = New W3CValidator(WholeDocumentText) 
    ValidationWorker.CancelAsync() 
    Dim TimerRetryUntilWorkerNotBusy As New Windows.Threading.DispatcherTimer 
    AddHandler TimerRetryUntilWorkerNotBusy.Tick, AddressOf WorkTicker 
    TimerRetryUntilWorkerNotBusy.Interval = New TimeSpan(1) '100 nanoseconds 
    TimerRetryUntilWorkerNotBusy.Start() 
End Sub 

Sub WorkTicker(ByVal sender As Object, ByVal e As System.EventArgs) 
    If ValidationWorker.IsBusy Then 
     Exit Sub 
    End If 
    DirectCast(sender, Windows.Threading.DispatcherTimer).Stop() 
    ValidationWorker.RunWorkerAsync(_ValidationArgument) 
    _ValidationArgument = Nothing 
End Sub 
1

En el fondo de bucle proceso de trabajo que necesita para comprobar si hay
backgroundWorkerPageProcess.CancellationPending
y salir en consecuencia. Entonces, una vez que exista, su ciclo while isBusy debe marcarse en consecuencia.

Actualización: Después de configurar Cancelar = verdadero, ¿está volviendo a salir del método? spitballing aquí Actualización 2: ¿Tiene el indicador WorkerSupportsCancellation establecido en true en el backgroundworker? También en método completado trabajador regresar si e.Cancelled .... más bolitas de papel

Actualización 3: después de algunas comprobaciones y compilación de mi propia aparece la maldita cosa que nunca sale de IsBusy dentro del mismo método. -Una opción es desactivar el botón mientras está ocupado y tener otro para cancelar, solo para que el usuario vuelva a hacer la validación. -o en su método completado trabajador si (e.Cancelado) llame a su método de validación con el texto apropiado ....

de cualquier manera es una especie de busto sin embargo. Lamento no ser de mucha ayuda aquí.

+0

Eso es lo que esperaba también. El método My DoWork() establece e.Cancel = True si DirectCast (remitente, BackgroundWorker) .CancellationPending. Pero IsBusy nunca regresó a False independientemente. –

+0

My DoWork() ejecuta "e.Cancel = True" y luego "Exit Sub" de inmediato. Mi RunWorkerCompleted() simplemente hace todo su trabajo dentro de una condición If: "If Not e.Cancelled Then Then ... End If End Sub". ¿Debo hacer más? –

+0

Sí. Establecí ValidationWorker.WorkerSupportsCancellation = True. ¿A qué te refieres con "volver a salir si se cancela"? –

8

intentar algo como esto:

bool restartWorker = false; 

    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
        // add other code here 
     if (e.Cancelled && restartWorker) 
     { 
      restartWorker = false; 
      backgroundWorker1.RunWorkerAsync(); 
     } 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if (backgroundWorker1.IsBusy) 
     { 
      restartWorker = true; 
      backgroundWorker1.CancelAsync(); 
     } 
     else 
      backgroundWorker1.RunWorkerAsync(); 
    } 
+1

¿Cómo modificar esto para pasar nuevos parámetros a RunWorkerAsync? – tofutim

+0

Encontré esta respuesta útil para un TextBox que busca sugerencias de una base de datos.Para pasar los parámetros uno usa RunWorkerAsync (objeto) en primer lugar y porque RunWorkerCompleted también se está ejecutando en el hilo de la interfaz de usuario, pase el nuevo valor allí. –

Cuestiones relacionadas