La implementación de 'sólo uno de' y 'no en paralelo' semántica con la biblioteca de tareas en paralelo

StackOverflow https://stackoverflow.com/questions/3613812

  •  26-09-2019
  •  | 
  •  

Pregunta

¿Cuál sería el mejor enfoque para la implementación de tareas con una clave que operan de la siguiente manera: -

Opción 1) Sólo uno de esta clave está siempre pendiente. Se puede utilizar, por ejemplo, de ASP.NET MVC que hacer cola un solo rinden una imagen en miniatura para no importa cuántas veces la imagen Url es golpeado. Sólo se corre, todas las demás solicitudes esperar a que se una a completa.

Opción 2) Todos los artículos con la misma clave deben ejecutar secuencialmente. Se puede utilizar por ejemplo para asegurar que las operaciones que recuperan un archivo desde un almacén de respaldo a una caché local no todos tratan de obtener el archivo de la memoria caché al mismo tiempo. La opción 1 es un caso especial de este donde las acciones posteriores con la misma clave son simplemente descartados (típicamente ahorra sólo un archivo-existe-cheque).

Tengo una WorkQueue existente que maneja tanto de estos casos (así como el estado de apartamentos, configuración y ThreadPriority grados máximos de paralelismo). TPL parece ser la mejor solución para la sustitución de éste y traerá opciones de cancelación mejoradas.

Tareas anidadas con continuaciones mirada de esperanza pero manteniendo un diccionario de tareas actualmente queue'd pronto se complica entre el TaskFactory y las clases TaskScheduler. Heredando de tareas es demasiado problemático ya que ni TaskFactory ni TaskScheduler son genéricos en la tarea.

La mayoría de tareas paralelas ejemplos asumen que el conjunto de tareas que se conoce de antemano. En este caso se añaden nuevas tareas todo el tiempo y necesidad de ser eliminados o encadenado a las tareas existentes en función de la operación solicitada y la clave se ha pasado.

¿Alguien ha implementado algo similar a esto el uso de TPL y si es así, qué enfoque tomó usted en su tarea, y las clases TaskScheduler TaskFactory?

¿Fue útil?

Solución

Tal vez, de una manera que puedo pensar es

  1. Crea una clase contenedora - KeyProcessor decir que hacer cola objetos para una llave.
  2. Método
  3. KeyProcessor.Run () será capaz de lo que sea la semántica de colas que necesita para. Esencialmente se buscaría cola interna para cualquier trabajo pendiente y luego seguir haciéndolo de forma secuencial.
  4. Mantener el diccionario de objetos KeyProcessor.
  5. Para cualquier nueva tarea, compruebe en el diccionario para la misma clave. Si no existe, entonces añadirlo. Cola la tarea en él. Si no su funcionamiento a continuación, programar con TPL utilizando el método de ejecución como la acción.
  6. Uso ContinueWith a la tarea mantenedor horario - por ejemplo, cuando la ejecución de tareas KeyProcessor.Run se ha completado, las tareas de continuación puede comprobar si hay más tareas programadas para la misma clave (ya que se ha completado) y comienzan de nuevo o eliminar de diccionario.

Todo lo anterior habría sido difícil desde el punto de sincronización hilo no para unos interesantes colecciones presentes en System.Collections.Concurrent espacio de nombres. Esto haría que la lógica anterior mucho más simple. Por ejemplo, ConcurrentDictionary.GetOrAdd permitirá a las operaciones de búsqueda y / o complemento el objeto KeyProcessor en forma de hilo de seguridad.

Otros consejos

Este problema es similar a uno que resolví en ReactiveXaml , aunque la mía también memoized solicitudes anteriores. Tome un vistazo al código para QueuedAsyncMRUCache (y su entrada de blog) - este código combina los TPL con las extensiones reactivas para obtener este tipo de cosas por hacer, pero hace que la garantía importante que la segunda solicitud de la misma clave bloqueará en la primera solicitud en vuelo en lugar de la emisión de otro.

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