¿Hay algún cambio que un Trabajador en segundo plano funcione mejor que Tareas en 5 segundos procesos en ejecución? Recuerdo haber leído en un libro que una Tarea está diseñada para procesos de ejecución corta.tarea fondo trabajador C#
El reasong lo que pido es esto:
Tengo un proceso que tarda 5 segundos para completar, y hay 4000 para completar los procesos. Al principio lo hice:
for (int i=0; i<4000; i++) {
Task.Factory.StartNewTask(action);
}
y esto tuvo un bajo rendimiento (después del primer minuto, 3-4 tareas en las que completada, y la aplicación de consola tenía 35 hilos). Tal vez esto fue estúpido, pero pensé que el grupo de subprocesos manejaría este tipo de situación (pondrá todas las acciones en una cola, y cuando un subproceso es libre, tomará una acción y lo ejecutará).
El segundo paso ahora era hacer manualmente los trabajadores de segundo plano Environment.ProcessorCount, y todas las acciones que se colocarán en un ConcurentQueue. Así que el código sería algo como esto:
var workers = new List<BackgroundWorker>();
//initialize workers
workers.ForEach((bk) =>
{
bk.DoWork += (s, e) =>
{
while (toDoActions.Count > 0)
{
Action a;
if (toDoActions.TryDequeue(out a))
{
a();
}
}
}
bk.RunWorkerAsync();
});
Esto se realizó de una manera mejor. Funcionó mucho mejor que las tareas incluso cuando tenía 30 trabajadores en segundo plano (tantas tareas como en el primer caso).
LE:
que iniciar las tareas de esta manera:
public static Task IndexFile(string file)
{
Action<object> indexAction = new Action<object>((f) =>
{
Index((string)f);
});
return Task.Factory.StartNew(indexAction, file);
}
Y el método del índice es la siguiente:
private static void Index(string file)
{
AudioDetectionServiceReference.AudioDetectionServiceClient client = new AudioDetectionServiceReference.AudioDetectionServiceClient();
client.IndexCompleted += (s, e) =>
{
if (e.Error != null)
{
if (FileError != null)
{
FileError(client,
new FileIndexErrorEventArgs((string)e.UserState, e.Error));
}
}
else
{
if (FileIndexed != null)
{
FileIndexed(client, new FileIndexedEventArgs((string)e.UserState));
}
}
};
using (IAudio proxy = new BassProxy())
{
List<int> max = new List<int>();
if (proxy.ReadFFTData(file, out max))
{
while (max.Count > 0 && max.First() == 0)
{
max.RemoveAt(0);
}
while (max.Count > 0 && max.Last() == 0)
{
max.RemoveAt(max.Count - 1);
}
client.IndexAsync(max.ToArray(), file, file);
}
else
{
throw new CouldNotIndexException(file, "The audio proxy did not return any data for this file.");
}
}
}
Este método lee de un mp3 presentar algunos datos, utilizando la biblioteca Bass.net. Luego, esos datos se envían a un servicio WCF, utilizando el método async. El método IndexFile (archivo de cadena), que crea tareas, se invoca 4000 veces en un ciclo for. Esos dos eventos, FileIndexed y FileError no se manejan, por lo que nunca se lanzan.
Es posible que desee utilizar 'BlockingCollection' en lugar de' ConcurrentQueue' (usará 'ConcurrentQueue' internamente). Hará que el código sea un poco más limpio y fácil de usar. – Servy
Gracias por la sugerencia ... Voy a cambiar :) –
¿Has probado 'Parallel.Invoke' con una variedad de acciones? – mellamokb