Cómo procesar elementos en cola en serie en un hilo de baja prioridad usando extensiones paralelas
-
27-09-2019 - |
Pregunta
Me gustaría saber cuál es la mejor manera de procesar los resultados de un proceso de larga ejecución en serie, pero en un hilo de baja prioridad utilizando el . NET 4.0 extensiones paralelas .
Tengo la clase siguiente que tanto hace la ejecución y proporciona los resultados:
public class Step
{
public string Name { get; set; }
public TimeSpan Duration { get; set; }
public bool Completed { get; set; }
public void Execute()
{
DateTime before = DateTime.Now;
RemotedService.DoSomeStuff();
Duration = DateTime.Now - before;
Completed = true;
}
}
¿Cómo puedo procesar estos pasos y guardarlos en un archivo, en orden, una vez procesadas? Me gustaría guardarlos en un archivo mientras RemotedService.DoSomeStuff()
está esperando una respuesta del servidor.
Escribir en el archivo sería así:
using (StreamWriter w = File.AppendText("myFile.txt"))
{
var completedStep = completedSteps.Dequeue();
w.WriteLine(string.Format("Completed {0} with result: {1} and duration {2}",
completedStep.Name,
completedStep.Completed,
completedStep.Duration));
}
Una opción que viene a la mente es añadirlos a una Queue
y tienen un Timer
que los procesos de ellas. Pero esto no se aprovecha del tiempo de inactividad de las llamadas Remoted.
Otra opción que viene a la mente es escribir de forma asíncrona cada resultado en el fichero usando un System.Threading.Tasks.Task
por Step
, pero eso no garantiza que se guardarán en orden y también se pueden introducir contienda con escribir en el archivo.
Solución
Yo sugeriría la creación de un BlockingCollection<Step>
(ver System.Collections.Concurrent
espacio de nombres). A medida que se completa cada paso, se añade a la colección. El comportamiento predeterminado de BlockingCollection
es funcionar como una cola, de manera que obtendrá el comportamiento FIFO que estás buscando.
Un segundo hilo de la cola de los servicios, la eliminación de cada elemento y escribirla en un archivo de registro.
Por lo tanto, si se ha añadido la cola:
static private BlockingCollection<Step> LogQueue = new BlockingCollection<Step>();
Se podría añadir a su método Execute
, una vez completado el artículo:
LogQueue.Add(this);
Y el hilo de la explotación forestal, la cual sería empezar en el constructor estático:
static void LoggingThread()
{
using (var w = new StreamWriter(...))
{
while (!LogQueue.IsCompleted())
{
Step item;
if (LogQueue.TryTake(out item))
{
w.WriteLine(....);
}
}
}
}
El hilo de la tala como he escrito que utiliza un hilo System.Threading
. Puede haber una manera más fácil o mejor que hacerlo con TPL. Aún no estoy terriblemente familiar con TPL, por lo que no podía decir.
Otros consejos
Un enfoque consiste en crear una costumbre programador de tareas (ver http: // MSDN .microsoft.com / es-es / library / ee789351.aspx ). Su programador de tareas personalizado puede limitar a la concurrencia de una en una sola vez y el estricto ejecución en orden.
Creación de un programador de tareas también le permite controlar la prioridad de hilo, o la ApartmentState que puede ser deseable en algunas situaciones.
Usted está literalmente describe el caso de uso para Workflow Foundation - que hace todas estas cosas para usted:)