cref - ¿C#debo crear un trabajador de fondo o muchos?
remarks c# (5)
Desde un punto de vista arquitectónico, es mejor tener un trabajador de fondo separado para cada tarea en segundo plano, que lógicamente no tiene relación con otras tareas de la clase.
Soy uno de esos programadores accidentales, por lo que no tengo mucho conocimiento sobre las mejores prácticas de programación.
Tengo una aplicación que actualmente utiliza 4 Background Worker.
Así que los declaro:
private BackgroundWorker bw1;
private BackgroundWorker bw2;
private BackgroundWorker bw3;
private BackgroundWorker bw4;
Luego configúralos:
bw1 = new BackgroundWorker();
bw1.WorkerReportsProgress = true;
bw1.DoWork += new DoWorkEventHandler(bw1_DoWork);
bw1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw1_RunWorkerCompleted);
bw1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw2 = new BackgroundWorker();
bw2.WorkerReportsProgress = true;
bw2.DoWork += new DoWorkEventHandler(bw2_DoWork);
bw2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw2_RunWorkerCompleted);
bw2.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw3 = new BackgroundWorker();
bw3.WorkerReportsProgress = true;
bw3.DoWork += new DoWorkEventHandler(bw3_DoWork);
bw3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw3_RunWorkerCompleted);
bw3.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw4 = new BackgroundWorker();
bw4.WorkerReportsProgress = true;
bw4.DoWork += new DoWorkEventHandler(bw4_DoWork);
bw4.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw4_RunWorkerCompleted);
bw4.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
Y luego uso el bw1.RunWorkerAsync (), bw2.RunWorkerAsync (), y así sucesivamente ...
La cosa es que nunca los llamo simultáneamente, se llaman en diferentes puntos de una manera bastante lineal.
Entonces, mi pregunta es: ¿es mejor tener muchos trabajadores de fondo "preconfigurados" o tener uno y cambiar los eventos DoWork y RunWorkerCompleted de acuerdo con lo que quiero que haga?
En general, es razonable usar varios subprocesos si ayuda con un uso más eficiente de los recursos en su sistema. Para tareas intensivas de CPU, un subproceso por núcleo de CPU es un buen punto de partida. Para las tareas intensivas de IO, ciertamente puede tener muchos más que eso.
Si tiene la flexibilidad de usar .NET 4, buscaría en la biblioteca paralela de tareas en lugar de BackgroundWorker. De manera predeterminada, tomará decisiones relativamente inteligentes sobre la cantidad de subprocesos que se ejecutarán simultáneamente, además de proporcionar un modelo de programación más sencillo.
Hacer el procesamiento con BackgroundWorker significa que lo haces en un hilo separado. Entonces, si no necesita multihilo, no hay necesidad de trabajadores de fondo separados. Si espera que finalice después de comenzar con cada uno de sus trabajadores, puede tener un solo trabajador. También puede eliminar algunos de los duplicados de código ...
Usted ejecuta los trabajadores para algún propósito computacional. Si el cálculo de una llamada se usa o depende de otra manera, puede usar más de un trabajador para lograr un mejor desempeño (por cierto, esto también es un tema para medir) Si solo necesita 4 trabajos y ejecútelos en un hilo separado solo para no bloquear la IU principal, un trabajador es una solución bastante buena.
Usualmente uso trabajadores de fondo en un patrón muy diferente. En lugar de definirlos todos al mismo tiempo al principio, incluidos sus respectivos controladores de eventos, los creo sobre la marcha cuando hago algo que los necesita.
public void SomeEventHandlerMaybe(object sender, EventArgs e) {
// do something
var bw = new BackgroundWorker();
bw.ReportsProgress = true;
bw.DoWork += delegate {
// do work. You can use locals from here
};
bw.ProgressChanged += delegate { ... };
bw.RunWorkerCompleted += delegate {
// do something with the results.
};
bw.RunWorkerAsync();
}
Algo como eso. Tiene el beneficio de que tiene todo el código que hace algo con o en el trabajador de fondo en un lugar y aproximadamente en el orden correcto también.