2010-04-24 14 views
29

he oído que el equipo .NET 4 ha añadido nuevas clases en el marco que hacen que trabajar con hilos de mejores y más fáciles.mejoras Multihilo en .NET 4

Básicamente, la pregunta es ¿cuáles son las nuevas formas de ejecutar las tareas multiproceso añadidas en .NET 4 y lo que están diseñados para ser utilizados para?

UPD: Sólo para que quede claro, no estoy en busca de una sola manera de ejecutar tareas en paralelo en .NET 4, quiero saber qué se añaden los nuevos, y si es posible lo situación cada uno de ellos será el más adecuado para ..

Respuesta

37

Con la falta de respuestas, me decidieron a evaluar en las respuestas a continuación con lo que he aprendido .. Como se ha indicado @ Scott, .NET 4 añadió la biblioteca de tareas en paralelo que añade una serie de innovaciones, nuevos métodos y enfoques al paralelismo.

  • Una de las primeras cosas que mencionar es los métodos Parallel.For y Parallel.ForEach, que permiten al desarrollador para procesar múltiples artículos en varios subprocesos. El Framework en este caso decidirá cuántos hilos son necesarios, cuándo crear nuevos hilos y cuándo no.
    Esta es una forma muy simple y directa de paralelizar el código existente y agregar algo de aumento de rendimiento.
  • Otra forma, algo similar a los enfoques anteriores es el uso de los extensores PLINQ. Toman una enumeración existente y la extienden con extensores de linq paralelos. Entonces, si tiene una consulta linq existente, puede convertirla fácilmente en PLINQ.Lo que esto significa es que todas las operaciones en PLINQ enumerable también tomarán ventaja de múltiples hilos, y el filtrado de su lista de objetos usando una cláusula .Where, por ejemplo, se ejecutará en múltiples hilos ahora.
  • Una de las innovaciones más grandes en el TPL es la nueva clase Task. De alguna manera, puede parecerse a la ya conocida clase Thread, pero aprovecha el nuevo Thread Pool en .NET 4 (que se ha mejorado mucho en comparación con versiones anteriores), y es mucho más funcional que la clase Thread normal. . Por ejemplo, puede encadenar Tareas donde las tareas en el medio de la cadena solo comenzarán cuando las anteriores terminen. Ejemplos y explicación detallada en un screencast en Channel 9
  • Para mejorar el trabajo con las clases de tareas, podemos usar el BlockingCollection<>. Esto funciona perfectamente en situaciones en las que tiene un escenario productor-consumidor. Puede tener varios hilos que producen algunos objetos, que luego serán consumidos y procesados ​​por métodos de consumo. Esto se puede paralelizar y controlar fácilmente con la fábrica de tareas y la colección de bloqueo. Screencast útil con ejemplos de Channel 9
    Estos también pueden usar diferentes clases de almacenamiento de respaldo (ConcurrentQueue, ConcurentStack, ConcurrentBag), que son todos seguros para hilos, y son diferentes en términos de orden de elementos y rendimiento. Ejemplos y explicaciones de ellos en otra video here
  • Otra cosa nueva que se ha agregado (que probablemente no forma parte del TPL, pero nos ayuda de todos modos) es la clase CountdownEvent, que puede ayudarnos en la "coordinación de tareas" escenarios "(c). Básicamente nos permite esperar hasta que todas las tareas paralelas hayan finalizado. Screencast con el ejemplo de uso en Channel 9

Se puede ver una serie de grabaciones de pantalla y vídeos en el canal 9 que están etiquetadas con "Parallel Computing"

+0

¿Hay algún código de muestra único productor/consumidor individual? – Xaqron

15

Sí, .NET 4 añadió el Task Parallel Library la que, en un nivel alto, añade soporte para:

  • correr paralelas con bucles y Parallel.ForParallel.ForEach
  • crear o ejecutar tareas utilizando Parallel.Invoke o la clase Task
  • PLINQ (LINQ paralelo a Objetos)

Respondiendo a la actualización de la pregunta original ...

El TPL es el preferido manera de escribir tareas paralelas usando .NET 4. Aún puede crear elementos de subprocesos usted mismo y hacer todas las mismas técnicas de subprocesamiento "manual" que antes. Lo que hay que tener en cuenta es que todo el grupo de subprocesos (y casi todo lo relacionado con el subprocesamiento) se ha reescrito para aprovechar el TPL. Esto significa que incluso si usted mismo crea un ítem de subprocesos, aún así termina usando el TPL, incluso si no lo sabe. Otra cosa a tener en cuenta es que el TPL está mucho más optimizado y se escalará de forma más adecuada en función de la cantidad de procesadores disponibles.

En cuanto a saber en qué situación de cada uno de ellos sería el más adecuado para, no hay una respuesta "bala de plata". Si anteriormente estaba haciendo cola con su propio elemento de subproceso de subprocesos (o si está haciendo algo de subprocesos múltiples), puede modificar esa parte de su código para usar el TPL sin ninguna consecuencia.

Por cosas como bucles paralelos o consultas en paralelo, tendrá que analizar el código y la ejecución de dicho código para determinar si es apropiado para ser parallelized.

+0

+1 para la referencia de TPL y un par de ejemplos ... Pero TPL es una biblioteca completa en .NET, mientras yo buscaba ejemplos más concretos ... –

+0

TPL es una biblioteca completa, pero se agregó como parte de .NET 4 y es la forma preferida de escribir aplicaciones enhebradas en .NET 4. Al ver cómo su respuesta y la mía son similares, no veo cómo esto no responde a su pregunta. –

+0

Sé que TPL se agregó en .NET4, y sé que es la forma preferida. Estaba pidiendo clases y metodologías dentro del tpl. Mi respuesta describe algunos de ellos + ejemplos, usted acaba de señalar 3 y ningún ejemplo/explicación en absoluto. –

1

Estrictamente hablando, esto es C# 4.0 y no una nueva clase, pero los acontecimientos now have a smarter form of locking que, si se yo he entendido correctamente el cambio, elimina la necesidad de reems de código de bloqueo como se muestra a continuación (tomado de this article por Jon Skeet):

SomeEventHandler someEvent; 
readonly object someEventLock = new object(); 

public event SomeEventHandler SomeEvent 
{ 
    add 
    { 
     lock (someEventLock) 
     { 
      someEvent += value; 
     } 
    } 
    remove 
    { 
     lock (someEventLock) 
     { 
      someEvent -= value; 
     } 
    } 
}