2011-07-21 13 views
5

Tengo varias acciones que quiero ejecutar en segundo plano, pero deben ejecutarse de forma síncrona una después de la otra.Creando una cola de ejecución usando Task.ContinueWith?

Me preguntaba si es una buena idea utilizar el método Task.ContinueWith para lograrlo. ¿Prevé algún problema con esto?

Mi código es como la siguiente:

private object syncRoot =new object(); 
private Task latestTask; 

public void EnqueueAction(System.Action action) 
{ 
    lock (syncRoot) 
    { 
     if (latestTask == null) 
      latestTask = Task.Factory.StartNew(action); 
     else 
      latestTask = latestTask.ContinueWith(tsk => action()); 
    } 
} 

Respuesta

5

Esto debería funcionar como fue diseñado (usando el hecho de que la TPL programará la continuación de inmediato si la tarea correspondiente ya ha completado).

Personalmente en este caso solo usaría un hilo dedicado usando una cola concurrente (ConcurrentQueue) para dibujar tareas de - esto es más explícito pero más fácil de analizar leyendo el código, especialmente si quiere averiguar, es decir, cuántas tareas están actualmente en cola, etc.

+0

Una mejora sería utilizar un BlockingCollection alrededor de ConcurrentQueue. Entonces uno puede enviar un hilo Tarea/Trabajador que solo usa un foreach sobre la colección de bloqueo. El foreach se "colgará" hasta que se agregue un nuevo elemento a la cola o se invoque CompleteAdding() en la colección de bloqueo. –

7

Hay un error en esto, que recientemente descubrí porque también estoy usando este método para asegurar que las tareas se ejecuten secuencialmente.

En mi aplicación tenía miles de instancias de estas mini-colas y rápidamente descubrí que tenía problemas de memoria. Como estas colas a menudo estaban inactivas, me mantuve en el último objeto de la tarea completa durante mucho tiempo y evité la recolección de basura. Dado que el objeto de resultado de la última tarea completada con frecuencia tenía más de 85,000 bytes, se asignó al Heap de objetos grandes (que no realiza la compactación durante la recolección de basura). Esto dio como resultado la fragmentación del LOH y el proceso de crecimiento continuo en tamaño.

Como hack para evitar esto, puede programar una tarea no operativa justo después de la real dentro de su bloqueo. Para una solución real, tendré que pasar a un método diferente de controlar la programación.

0

Utilicé este fragmento y parece que funciona como se diseñó. El número de instancias en mi caso no se ejecuta en miles, sino en un solo dígito. Sin embargo, no hay problemas hasta el momento.

Me interesaría el ejemplo de ConcurrentQueue, si hay alguno?

Gracias

+0

Para una cola súper simple, esto funciona bien para mí todavía. Pero formó colas de tareas más complicadas que he comenzado a utilizar [Dataflow] (http://msdn.microsoft.com/en-us/library/hh228603 (v = vs.110) .aspx) más. – lukebuehler

Cuestiones relacionadas