BackgroundWorker vs hilo de fondo


Tengo una pregunta estilística sobre la elección de la implementación del hilo de fondo que debo usar en una aplicación de formulario de Windows. Actualmente tengo un BackgroundWorker en una forma que tiene un bucle infinito (while(true)). En este bucle utilizo WaitHandle.WaitAny para mantener el hilo de repetición hasta que sucede algo de interés. Uno de los manejadores de eventos que espero es un evento "StopThread" para que pueda salir del bucle. Este evento se indica cuando desde mi reemplaza Form.Dispose().

Leí en alguna parte que BackgroundWorker está realmente destinado a operaciones con las que no desea atar la interfaz de usuario y tener un fin finito, como descargar un archivo o procesar una secuencia de elementos. En este caso, el" final " es desconocido y solo cuando la ventana está cerrada. Por lo tanto, ¿sería más apropiado para mí usar un hilo de fondo en lugar de BackgroundWorker para este propósito?

Author: Naser Asadi, 2009-10-02

11 answers

Desde mi comprensión de tu pregunta, estás usando un BackgroundWorker como hilo estándar.

La razón por la que se recomienda BackgroundWorker para las cosas que no desea atar el subproceso de interfaz de usuario es porque expone algunos eventos agradables al hacer el desarrollo de Formularios Win.

Eventos como RunWorkerCompleted para señalar cuando el subproceso ha completado lo que necesitaba hacer, y el evento ProgressChanged para actualizar la interfaz gráfica de usuario en el progreso de los subprocesos.

Así que si no están haciendo uso de estos, no veo ninguno daño en el uso de un hilo estándar para lo que necesita hacer.

 76
Author: ParmesanCodice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-04 08:55:11

Algunos de mis pensamientos...

  1. Use BackgroundWorker si tiene una sola tarea que se ejecuta en segundo plano y necesita interactuar con la interfaz de usuario. La tarea de ordenar llamadas de datos y métodos al subproceso de interfaz de usuario se maneja automáticamente a través de su modelo basado en eventos. Evitar BackgroundWorker si...
    • su ensamblado no tiene o no interactúa directamente con la interfaz de usuario,
    • necesita que el hilo sea un hilo en primer plano, o
    • es necesario manipular el prioridad de hilo.
  2. Use un subproceso ThreadPool cuando se desea eficiencia. El ThreadPool ayuda a evitar la sobrecarga asociada con la creación, inicio y detención de subprocesos. Evite usar el ThreadPool si...
    • la tarea se ejecuta durante toda la vida de su aplicación,
    • necesitas que el hilo sea un hilo en primer plano,
    • necesitas manipular la prioridad del hilo, o
    • necesita que el hilo tenga una identidad fija (abortar, suspender, descubrir).
  3. Use la clase Thread para tareas de larga duración y cuando necesite características ofrecidas por un modelo formal de subprocesos, por ejemplo, elegir entre subprocesos en primer plano y en segundo plano, ajustar la prioridad del subproceso, control detallado sobre la ejecución del subproceso, etc.
 341
Author: Matt Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-22 13:12:11

Más o menos lo que dijo Matt Davis, con los siguientes puntos adicionales:

Para mí el principal diferenciador con BackgroundWorker es el marshalling automático del evento completado a través del SynchronizationContext. En un contexto de IU, esto significa que el evento completado se activa en el subproceso de IU, por lo que se puede usar para actualizar la IU. Este es un diferenciador importante si está utilizando BackgroundWorker en un contexto de interfaz de usuario.

Las tareas ejecutadas a través de ThreadPool no se pueden cancelar fácilmente (esto incluye ThreadPool. QueueUserWorkItem y los delegados ejecutan asíncronamente). Así que mientras evita la sobrecarga del hilo spinup, si necesita cancelación, use un BackgroundWorker o (más probablemente fuera de la interfaz de usuario) gire un hilo y mantenga una referencia a él para que pueda llamar a Abort().

 11
Author: piers7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-17 17:16:27

También está atando un hilo threadpool durante la vida útil del trabajador en segundo plano, lo que puede ser motivo de preocupación, ya que solo hay un número finito de ellos. Yo diría que si solo está creando el hilo una vez para su aplicación (y no utiliza ninguna de las características de background worker), entonces use un hilo, en lugar de un hilo backgroundworker/threadpool.

 10
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-02 00:08:35

Ya sabes, a veces es más fácil trabajar con un BackgroundWorker independientemente de si estás usando Windows Forms, WPF o cualquier tecnología. La parte buena de estos chicos es que obtienes threading sin tener que preocuparte demasiado sobre dónde se está ejecutando el hilo, lo cual es ideal para tareas simples.

Antes de usar un BackgroundWorker considere primero si desea cancelar un hilo (aplicación de cierre, cancelación de usuario), entonces debe decidir si su hilo debe verificar las cancelaciones o si debe ser empujado sobre la ejecución en sí.

BackgroundWorker.CancelAsync() establecerá CancellationPending a true pero no hará nada más, entonces es responsabilidad de los hilos comprobar continuamente esto, tenga en cuenta también que podría terminar con una condición de carrera en este enfoque donde su usuario canceló, pero el hilo completado antes de la prueba para CancellationPending.

Thread.Abort() por otro lado lanzará una excepción dentro de la ejecución del subproceso que obliga a la cancelación de ese subproceso, debe tener cuidado con lo que podría ser peligroso si esta excepción se planteó de repente dentro de la ejecución, sin embargo.

El enhebrado necesita una consideración muy cuidadosa sin importar cuál sea la tarea, para una lectura adicional:

Programación paralela en. NET Framework Mejores Prácticas de Enhebrado Gestionado

 8
Author: Brett Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-21 10:27:59

Sabía cómo usar hilos antes de conocer.NET, así que me tomó un poco acostumbrarme cuando comencé a usar BackgroundWorkers. Matt Davis ha resumido la diferencia con gran excelencia, pero agregaría que es más difícil comprender exactamente lo que está haciendo el código, y esto puede hacer que la depuración sea más difícil. Es más fácil pensar en crear y cerrar hilos, IMO, que pensar en dar trabajo a un grupo de hilos.

Todavía no puedo comentar las publicaciones de otras personas, así que perdona mi cojera momentánea al usar una respuesta para dirigirme a piers7

No uses Hilo.Abort (); en su lugar, señale un evento y diseñe su hilo para que termine correctamente cuando se indique. Hilo.Abort () genera una ThreadAbortException en un punto arbitrario en la ejecución del hilo, que puede hacer todo tipo de cosas infelices como monitores huérfanos, estado compartido corrupto, y así sucesivamente. http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

 4
Author: ajs410,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-28 20:31:29

Si no está roto, arréglalo hasta que lo esté...solo bromeo:)

Pero en serio BackgroundWorker es probablemente muy similar a lo que ya tiene, si hubiera comenzado con él desde el principio, tal vez habría ahorrado algo de tiempo, pero en este punto no veo la necesidad. A menos que algo no esté funcionando, o creas que tu código actual es difícil de entender, entonces me quedaría con lo que tienes.

 2
Author: Gandalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-01 22:34:08

La diferencia básica es, como usted ha indicado, generar eventos GUI desde BackgroundWorker. Si el subproceso no necesita actualizar la pantalla o generar eventos para el subproceso principal de la GUI, entonces puede ser un subproceso simple.

 2
Author: David R Tribble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-01 23:09:51

Un trabajador en segundo plano es una clase que funciona en un subproceso separado, pero proporciona una funcionalidad adicional que no se obtiene con un subproceso simple (como el manejo del informe de progreso de la tarea).

Si no necesita las características adicionales dadas por un trabajador en segundo plano - y parece que no - entonces un hilo sería más apropiado.

 1
Author: Cesar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-01 22:34:57

Quiero señalar un comportamiento de la clase BackgroundWorker que aún no se mencionó. Puede hacer que un hilo normal se ejecute en segundo plano configurando el hilo.Es propiedad de fondo.

Los subprocesos de fondo son idénticos a los subprocesos de primer plano, excepto que los subprocesos de fondo no impiden que un proceso termine. [1]

Puede probar este comportamiento llamando al siguiente método en el constructor de su ventana de formulario.

void TestBackgroundThread()
{
    var thread = new Thread((ThreadStart)delegate()
    {
        long count = 0;
        while (true)
        {
            count++;
            Debug.WriteLine("Thread loop count: " + count);
        }
    });

    // Choose one option:
    thread.IsBackground = false; // <--- This will make the thread run in background
    thread.IsBackground = true; // <--- This will delay program termination

    thread.Start();
}

Cuando el La propiedad IsBackground se establece en true y cierra la ventana, luego su aplicación terminará normalmente.

Pero cuando la propiedad IsBackground se establece en false (de forma predeterminada) y cierra la ventana, entonces solo la ventana desaparecerá, pero el proceso seguirá ejecutándose.

La clase BackgroundWorker utiliza un hilo que se ejecuta en segundo plano.

 1
Author: Doomjunky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 14:05:34

Lo que me desconcierta es que el diseñador de visual studio solo le permite usar BackgroundWorkers y Temporizadores que en realidad no funcionan con el proyecto de servicio.

Te da controles de arrastrar y soltar en tu servicio pero... ni siquiera intentes desplegarlo. No funcionará.

Servicios: Utilice solamente el Sistema.Temporizador.Temporizador Sistema.Windows.Forma.El temporizador no funcionará aunque esté disponible en la caja de herramientas

Servicios: BackgroundWorkers no funcionará cuando se está ejecutando como un Servicio Usa el Sistema.Enhebrando.ThreadPools en su lugar o llamadas Asincrónicas

 0
Author: scottweeden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-17 03:29:31