2011-01-11 10 views
16

Tengo un par de situaciones en mi código donde varios subprocesos pueden crear elementos de trabajo que, por diversas razones, no deberían hacerse en paralelo. Me gustaría asegurarme de que el trabajo se realice de forma FIFO, independientemente de qué hilo proceda. En Java, colocaba los elementos de trabajo en un solo subproceso ExecutorService; ¿hay un equivalente en C#? He improvisado algo con un Queue y un montón de bloques lock(){}, pero sería bueno poder usar algo y probarlo.C# equivalente para Java ExecutorService.newSingleThreadExecutor(), o: cómo serializar acceso multiproceso a un recurso

Actualización: ¿Alguien tiene experiencia con System.Threading.Tasks? ¿Tiene una solución para este tipo de cosas? Estoy escribiendo una aplicación de Monotouch, así que quién sabe si podría encontrar una versión de respaldo para poder trabajar, pero al menos sería algo en lo que pensar en el futuro.

Actualización # 2 Para desarrolladores de C# no familiarizados con las bibliotecas de Java, básicamente quiero algo que permita que varios hilos entreguen elementos de trabajo para que todos esos elementos de trabajo se ejecuten en un solo hilo (que no es ninguno de los hilos de llamada).

+0

Si el trabajo debe hacerse de una manera FIFO, ¿por qué crear "varios" subprocesos? ¿Por qué no hacer el trabajo en un solo hilo? – Mark

+0

@ Mark Los diversos hilos existen por otros motivos: parte del trabajo se desencadena por actividad de IU, algunos por respuestas a solicitudes de red, y otros por temporizadores. –

+0

A esta pregunta: "¿cómo serializar el acceso multiproceso a un recurso?" usted mismo ha respondido: utilice la instrucción lock() en sus recursos (o un objeto que los encapsule). – BertuPG

Respuesta

3

Puede usar ConcurrentQueue, (si monotouch admite .net 4?) Es seguro para los hilos y I piensa que la implementación es realmente sin cerradura. Esto funciona bastante bien si tiene una tarea larga (como en un servicio de Windows).

En general, su problema parece que tiene varios productores con un solo consumidor.

var work = new ConcurrentQueue<Item>(); 
var producer1 = Task.Factory.StartNew(() => { 
    work.Enqueue(item); // or whatever your threads are doing 
}); 
var producer2 = Task.Factory.StartNew(() => { 
    work.Enqueue(item); // etc 
}); 
var consumer = Task.Factory.StartNew(() => { 
    while(running) { 
     Item item = null; 
     work.TryDequeue(out item); 
    } 
}); 
Task.WaitAll(producer1, producer2, consumer); 

Debe utilizar BlockingCollection si usted tiene una piscina finito de elementos de trabajo. Here's an MSDN page mostrando todos los nuevos tipos de colecciones concurrentes.

1

Yo creo esto se puede hacer usando un SynchronizationContext. Sin embargo, solo he hecho esto para publicar de nuevo en el hilo de la interfaz de usuario, que ya tiene un contexto de sincronización (si se dice que está instalado) proporcionado por .NET. No sé cómo prepararlo para utilizarlo desde un "hilo vainilla". " aunque.

Algunos enlaces que he encontrado para "proveedor de SynchronizationContext personalizada" (No he tenido tiempo para revisar estos síntomas, no comprender plenamente el trabajo/contexto, ni tengo ninguna información adicional):

  1. Looking for an example of a custom SynchronizationContext (Required for unit testing)

  2. http://codeidol.com/csharp/wcf/Concurrency-Management/Custom-Service-Synchronization-Context/

de codificación feliz.

-2

Como escribí en los comentarios, descubriste por tu cuenta que la declaración lock puede hacer el trabajo.

Si está interesado en obtener un "contenedor" que pueda simplificar el trabajo de administrar una cola de elementos de trabajo, consulte la clase ThreadPool.

Creo que, en una arquitectura bien diseñada, con estos dos elementos (clase ThreadPool y declaración lock) puede serializar fácil y exitosamente los recursos.

+2

La frase relevante en mi pregunta es "improvisada", y la relevante en su respuesta es "en una arquitectura bien diseñada". De hecho, si bien no voy a ser cruel y votar por él, "las herramientas existen, ve cómo se construye" no es realmente una respuesta. –

+0

Puedes votar lo que quieras. No tengo tiempo para hacer un ejemplo completo que te permita copiar y pegar y hacer tu trabajo. Escribiste sobre Cola, supuse que la usabas para administrar hilos, y te sugerí que miraras la clase ThreadPool para simplificar tu trabajo. ¿Qué pasa?!? – BertuPG