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.

¿Fue útil?

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:)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top