none
Proceso con backgroundworker cada cierto tiempo .Cortar sleep al Cancelar RRS feed

  • Pregunta

  • hola grupo:
    Tengo una aplicacion que usa el control BackgroundWorker y tengo en el formulario un boton Cancelar y otro Aceptar 
    La Aplicacion realiza un proceso cada x intervalos de tiempo, segun  lo que ingresa el usuario en un textbox (en minutos) . En el codigo este control lo hago con un
    el tema esta cuando presiono cancelar y  justo ahi el proceso entra en sleep no se como romper el sleep para  que cancele de inmediato.

    Por ahora lo unico que puedo hacer es verificar el estado del backgroundworker , antes y despues del sleep para ver si se cancelo o no :
    (y tambien en varias partes del codigo pero no se si es lo mas eficiente)

      private bool VerificarCancelacionProceso(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker bgw = sender as BackgroundWorker;
                if (bgw.CancellationPending)
                {
                    e.Cancel = true;
                    return true;
                }
                else return false;
            }

    El codigo del do work es el siguiente :

    private void bgw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker bgw = sender as BackgroundWorker; while (!bgw.CancellationPending) { RealizarMonitoreo(); if (VerificarCancelacionProceso(sender, e)) { return; } bgw.ReportProgress(1, " Esperando... " + Convert.ToString(Intervalo / 60000) + "minutos"); System.Threading.Thread.Sleep(Intervalo); if (VerificarCancelacionProceso(sender, e)) { return; } bgw.ReportProgress(1, " Volviendo a Iniciar Proceso... "); }

    Espero se entienda. 

    Cualquier ayuda sera agradecida


    miércoles, 22 de febrero de 2012 14:48

Respuestas

  • Cambie el Sleep() por un evento de sincronización.  Explico mejor:

    1. Declare un objeto de tipo System.Threading.AutoResetEvent.
    2. En DoWork(), cambie el Sleep() por una llamada al método WaitOne() del objeto en #1.
    3. El botón de cancelar llama al método CancelAsync() del background worker y también al método Set() del objeto en #1.
    //A nivel de clase:
    System.Threading.AutoResetEvent evCancelar;
    
    //En el Load del formulario:
    evCancelar = new System.Threading.AutoResetEvent();
    
    //En el evento click del botón Cancelar:
    backgroundWorker1.CancelAsync();
    evCancelar.Set();
    
    //En el DoWork, en vez de Sleep:
    evCancelar.WaitOne(new TimeSpan(0, losMinutos, 0));


    Jose R. MCP

    • Marcado como respuesta sebastian viga miércoles, 22 de febrero de 2012 16:30
    miércoles, 22 de febrero de 2012 15:20
    Moderador

Todas las respuestas

  • Cambie el Sleep() por un evento de sincronización.  Explico mejor:

    1. Declare un objeto de tipo System.Threading.AutoResetEvent.
    2. En DoWork(), cambie el Sleep() por una llamada al método WaitOne() del objeto en #1.
    3. El botón de cancelar llama al método CancelAsync() del background worker y también al método Set() del objeto en #1.
    //A nivel de clase:
    System.Threading.AutoResetEvent evCancelar;
    
    //En el Load del formulario:
    evCancelar = new System.Threading.AutoResetEvent();
    
    //En el evento click del botón Cancelar:
    backgroundWorker1.CancelAsync();
    evCancelar.Set();
    
    //En el DoWork, en vez de Sleep:
    evCancelar.WaitOne(new TimeSpan(0, losMinutos, 0));


    Jose R. MCP

    • Marcado como respuesta sebastian viga miércoles, 22 de febrero de 2012 16:30
    miércoles, 22 de febrero de 2012 15:20
    Moderador
  • gracias jose funciono, solo que en el load del formulario hay que pasasle false al constructorSystem.Threading.AutoResetEvent

    evCancelar = new System.Threading.AutoResetEvent(false);

    dejo mi codigo do work si les sirve: 

       {
                BackgroundWorker bgw = sender as BackgroundWorker;
                while (!bgw.CancellationPending)
                {
                    RealizarMonitoreo();
                    if (VerificarCancelacionProceso(sender, e))
                    {
                        return;
                    }
                    bgw.ReportProgress(1, "  Esperando... " + Convert.ToString(Intervalo / 60000) + " minutos...");
                    temporizador = Stopwatch.StartNew();
                    // System.Threading.Thread.Sleep(Intervalo);
                    evCancelar.WaitOne(new TimeSpan(0, Intervalo / 60000, 0));


                    lbltiempo.Invoke(new notificacion(ActualizarTiempo), temporizador.Elapsed.Minutes.ToString());


                    if (VerificarCancelacionProceso(sender, e))
                    {
                        return;
                    }
                    
                    bgw.ReportProgress(1, "  Volviendo a Iniciar Proceso... ");
                }

     Saludos.

    miércoles, 22 de febrero de 2012 16:29