none
Backgroundworker con dos hilos ? RRS feed

  • Pregunta

  • hola grupo :

    Sigo con aplicacion de thread :) , y tengo la siguiente problematica:

    Tengo una aplicacion que usa el control BackgroundWorker y tengo en el formulario un boton Cancelar
    y otro ejecutar/aceptar
    al presionar ejecutar la Aplicacion realiza un proceso cada x intervalos de tiempo, segun  lo que ingresa el usuario en un textbox (en minutos).
    Toda la logica de la aplicacion que estoy haciendo esta en un proceso llamado realizarmonitoreo que esta en el dowork

    (en este hilo  http://social.msdn.microsoft.com/Forums/es-AR/winformses/thread/4182d809-c3f6-46a1-a5c4-1e6cfb762a25)

    Ahora el usuario quiere que agregue otro boton que se llame forzar que llame a realizar monitoreo

    Podria hacer lo siguiente: ?  
    1)agregar otro Backgroundworker o agregar otro hilo  ?
    2) si no uso otro hilo uzando el mismo : La idea mia era reutilizar el do work , pero evitando la espera (evitar el evCancelar.WaitOne)

    el do work , del thread actual lo tengo asi

     BackgroundWorker bgw = sender as BackgroundWorker;
      while (!bgw.CancellationPending)
                {
                  
                    RealizarMonitoreo();
                   
                    if (VerificarCancelacionProceso(sender, e))
                    {
                        return;
                    }
                   
                                  
                    evCancelar.WaitOne(new TimeSpan(0, Intervalo / 60000, 0));
    }

    Estoy perdido con el tema , cualquier sugerencia sera bienvenida.


    gracias como siempre.




    viernes, 24 de febrero de 2012 19:52

Respuestas

  • hola perdon la demora , lo solucione volviendo al esquema  que tenia del principio, y use una variable global forzar ,cdo presiono el boton forzar asigno true a esa variable,   y dentro del do work hago lo siguiente (es la unica que se me ocurrio usando el mismo thread )

                if (Forzar)
                {
                    RealizarMonitoreo();
                    e.Cancel = true;
                    statusStrip1.Invoke(new notificacion(ActualizarBarraEstado), "...Ultima Actualizacion(Forzada): " + DateTime.Now);
                    return;
                }
                while (!bgw.CancellationPending)
                {
                 
                    RealizarMonitoreo();
                  
                    if (VerificarCancelacionProceso(sender, e))
                    {
                        return;
                    }
                  
                                  
                    evCancelar.WaitOne(new TimeSpan(0, Intervalo / 60000, 0));
                   }


                private void btn_forzar_Click(object sender, EventArgs e)
                {
                Forzar = true;
                bgw.RunWorkerAsync();
                this.btnActualizar.Enabled = false;
                this.btn_Cancelar.Enabled = false;

                }

    (el forzar corre el proceso una vez sola y cancela , para no esperar es otra variante )

    gracias.

    martes, 28 de febrero de 2012 13:28

Todas las respuestas

  • Hola, 

    Simplemente creo que podrias plantearlo algo mejor, es decir ahora mismo tienes un hilo (background worker) ocupado siempre con un bucle infinito, igual tienes suerte y no te consume mucha cpu pero no creo que sea recomendable.

    Te proponga una idea más sencilla y haber si se adapta a tu necesidad.

    Se trata de crear un Timer y un BackgroundWorker:

    • En el DoWork del BakgroundWorker solamente llama al proceso RealizarMonitoreo (entiendo que esto es costosoy por eso esta en un hilo aparte).
    • Por otra parte el intervalo asignalo a la propiedad interval del Timer y usa el metodo Start() del timer para encenderlo
    • Entonces en el evento Elapsed (igual el nombre no era este) del timer ejecutas el backgroundworker [backgroundworker.RunWorkAsync() ] de esta forma tenemos todo como tienes ahora.
    • Y el boton Forzar que necesitas hara lo mismo que el timer un RunWorkerAsync.

    Antes de ejecutar el runworkerasync yo de ti miraria la propiedad IsBusy del worker, ya que sino petara :P

    A mi modo de ver esto es más sencillo y si el intervalo es configurable en tiempo real no tienes más que cambiar la propiedad interval del timer.

    Saludos!


    Vota mi respuesta si te ha sido útil. Gracias.

    viernes, 24 de febrero de 2012 21:04
  • Gracias por responder David,

    El proceso  Realizarmonitoreo  es  un poco pesado pero no tanto ,  lo puse en un hilo aparte porque no me deja acceder a la interfaz de usuario para presionar el boton cancelar proceso.

    lo que me planteaste esta bueno y es mas sencillo ,lo  voy a probar

     lo unico que no se si es igual  el start/stop del timer con poner enabled/disabled  en el ejecutar y cancelar de esta forma

    (voy a probar )
    en el ejecutar voy a escribir lo siguiente:

    if( !bgw.IsBusy)
    {
    timer.enabled = true }

    en el cancelar esto:

    timer.enabled = false
    bgw.CancelAsync();

    en el tick del timer

    bgw.RunWorkerAsync

    gracias de nuevo



    viernes, 24 de febrero de 2012 21:30
  • En realidad el Start/Stop del timer lo que hace es poner el Enabled a true y false, quizas sintacticamente usando el metodo queda mas claro, pero el comportamiento es el mismo.

    Luego, en el boton cancelar, la instruccion bgw.CancelAsync(); seria correcta, pero si haces un Stop o Enabled=false del timer, este nunca más se ejecutará. Quizas solamente deberias cancelar el backgroundworker y asi en el proximo intervalo el timer se volvera a lanzar, pero vamos tu mejor que nadie sabrás que quieres hacer jeje

    PD: Vota la respuesta o marca como respuesta asi otra gente verá la solucion mas facilmente


    Vota mi respuesta si te ha sido útil. Gracias.

    sábado, 25 de febrero de 2012 10:30
  • gracias otra vez,

    Si el tema esta en que al presionar  el boton cancelar llamo al  bgw.CancelAsync();
    y tengo que esperar al evento del timer llame timerProceso_Tick que llama al bagroundwoker y entre en el do work
    y verfique  que se cancelo el proceso ( if (bgw.CancellationPending)  entonces e.cancelar = cancelar.)

    Entonces la pantalla de mi aplicacion despues de cancelar se queda un tiempo ,hasta que vuelva a ejecutarse el timer para cancelar.
    y no cancela   de inmedito

      private void timerProceso_Tick(object sender, EventArgs e)
            {

                    {
                        bgw.RunWorkerAsync();
     
              
            }

    gracias


    sábado, 25 de febrero de 2012 14:09
  • hola perdon la demora , lo solucione volviendo al esquema  que tenia del principio, y use una variable global forzar ,cdo presiono el boton forzar asigno true a esa variable,   y dentro del do work hago lo siguiente (es la unica que se me ocurrio usando el mismo thread )

                if (Forzar)
                {
                    RealizarMonitoreo();
                    e.Cancel = true;
                    statusStrip1.Invoke(new notificacion(ActualizarBarraEstado), "...Ultima Actualizacion(Forzada): " + DateTime.Now);
                    return;
                }
                while (!bgw.CancellationPending)
                {
                 
                    RealizarMonitoreo();
                  
                    if (VerificarCancelacionProceso(sender, e))
                    {
                        return;
                    }
                  
                                  
                    evCancelar.WaitOne(new TimeSpan(0, Intervalo / 60000, 0));
                   }


                private void btn_forzar_Click(object sender, EventArgs e)
                {
                Forzar = true;
                bgw.RunWorkerAsync();
                this.btnActualizar.Enabled = false;
                this.btn_Cancelar.Enabled = false;

                }

    (el forzar corre el proceso una vez sola y cancela , para no esperar es otra variante )

    gracias.

    martes, 28 de febrero de 2012 13:28