2010-07-24 11 views
6

(Editar: aclarar, mi meta principal es la simultaneidad, pero no necesariamente para múltiples núcleos máquinas)Dibujo multiproceso en .NET?

Soy bastante nuevo a todos los conceptos sobre la concurrencia, pero me di cuenta de que necesitaba tener rutinas paralelas dibujo, por una serie de razones:

  • quería dibujar diferentes partes de un gráfico separadamente (fondo actualizan con menos frecuencia que en primer plano, guardado en una memoria intermedia).
  • Quería control sobre la prioridad (Más prioridad a la capacidad de respuesta de la IU que dibujar un gráfico complejo).
  • Quería hacer cálculos de dibujo por cuadro multiproceso.
  • Quería ofrecer cancelación para rutinas de dibujo complejas en el búfer.

Sin embargo, al ser un principiante, mi código pronto parecía un desastre y la refacturación o corrección de errores se volvió tan incómoda que decidí que tenía que jugar más con él antes de hacer algo serio.

Así que me gustaría saber cómo hacer un código .NET multiproceso limpio, fácil de mantener que tenga sentido cuando lo miro después de despertarme al día siguiente. El problema más grande que tenía era estructurar la aplicación para que todas las partes hablaran entre sí de una manera inteligente (en lugar de torpe y hacky).

Cualquier sugerencia es bienvenida, pero no tengo una preferencia por las fuentes que puedo digerir en mi tiempo libre (por ejemplo, no más de 500 páginas de un tratado sobre la concurrencia) y para C#/VB.NET, hasta la última versión (ya que veo que ha habido advances). Básicamente, quiero algo directo al grano, así que puedo comenzar jugando con los conceptos en mis proyectos de juguetes.

+0

Describir sus necesidades con más detalle ayudará a las personas a responder su pregunta. ¿Quieres dibujar toda la interfaz de usuario de forma multiproceso? ¿Tiene un solo control que debe ser multiproceso? Probablemente terminará con un grupo de subprocesos consumiendo sus capas de dibujo. –

+0

Lo siento, mi principal preocupación es estructurar dicho código (que normalmente es sincrónico) de manera concurrente. En este caso, se trata de un solo control que podría dividir su dibujo en dos o tres hilos, pero lo que me dificulta es comprender cómo se puede aplicar la concurrencia a algo que normalmente se inicia y finaliza en un evento Paint. –

Respuesta

1

El Task Parallel Library es definitivamente el lugar que debe buscar para simplificar su código. Personalmente he escrito una introducción (semi-larga) al Parallelism with .NET 4 que cubre bastantes conceptos que podrían ser útiles.

Tenga en cuenta, sin embargo, que probablemente deba considerar dejar el dibujo de un solo hilo. Debería tratar de mantener el cálculo multiproceso y las operaciones reales de dibujo en el hilo de la GUI.

La mayoría de las API de dibujo requieren que todas las llamadas de dibujo real sucedan en el mismo contexto de sincronización.

Dicho esto, utilizando las nuevas clases de recopilación como ConcurrentQueue simplifique este tipo de código. Intente pensar en términos de muchos subprocesos (productores) agregando "operaciones de dibujo" a una cola concurrente compartida, y un hilo (el consumidor) tomando las operaciones y realizándolas.

Esto le ofrece un diseño razonablemente escalable, pero bastante simple en el que puede construir.

+0

Hehe Tengo uno de los artículos de su introducción que ya está abierto en otra pestaña y debo decir que es impresionante (y la mejor fuente que he encontrado hasta ahora), rápidamente estoy tomando conocimiento de ello. Respecto al código de dibujo, como ya he dicho, el "fondo" es un poco más complejo (y podría dibujarse en un buffer mientras que los elementos ligeros se superponen en el buffer anterior), pero el principal problema al que me enfrento es compartir dichos buffers en un moda elegante en los hilos (y llamar a las funciones de renderizado en el momento adecuado en lugar de colocarlas en el evento de pintura). –

+0

Seguiré leyendo sus artículos y jugando con el código, tal vez eso vale más que un gran libro sobre el tema (para mis humildes necesidades del codificador). ¡Por ahora, felicitaciones +1 e ilimitadas para ti! :) –

+0

@Camilo: FYI - El mejor libro que he visto hasta ahora es el libro de P & P (fui revisor);). Se lanzará el próximo mes, pero puedes leer la vista previa en: http://parallelpatterns.codeplex.com/ –

9

pero me di cuenta de que necesitaba tener rutinas de dibujo paralelos

Tres palabras: no bajo Windows.

Simple así. El dibujo estándar de ventanas tiene un solo subproceso por definición, por razones de compatibilidad. Cualquier control de UI (sigamos con el.NET world) SÓLO se manipulará a partir de su hilo creacional (por lo que en realidad es más brutal que un solo hilo - es UN HILO ESPECÍFICO SOLAMENTE).

Usted puede hacer el cálculo previo por separado, pero el dibujo real tiene t OBE hecho de que un hilo.

MENOS asignar un mapa de bits, tener su propio dibujo allí, y luego girar a que el hilo de interfaz de usuario para la pintura sobre la ventana.

Esto no tiene nada que ver con toda la tarea Parallel Library etc. (que downvoted) sino que se remonta a la ciudad un requisito muy antiguo que se mantiene en torno a la razón simplicidad y compatibilidad. Esta es la razón por la cual cualquier subproceso de la interfaz de usuario debe comercializarse como un departamento roscado de síntesis.

También tenga en cuenta que el dibujo con múltiples hilos, si lo implementa usted mismo, tiene serias implicaciones. ¿Cuál gana ópticamente (permanece en primer plano)? Esto no es realmente determinable cuando se usa multihilo. Sin embargo, eres libre de probarlo.

En este caso:

  • Tener su propio buffer y la sincronización es una necesidad. Aléjese de cualquier biblioteca de gráficos de Windows (WPF o Winforms) excepto en el último paso (enriquecer su mapa de bits).

  • DirectX 11 supuestamente tiene algún tipo de apoyo para las llamadas de varios hilos, pero no estoy seguro qué tan lejos va.

+0

De hecho, tenía rutinas de dibujo en otro hilo que dibujaba en un buffer, y dibujé ese búfer en el subproceso de UI con DrawImageUnscaled(), e incluso estaba usando GDI + (en los subprocesos de dibujo), ya que su rendimiento está bien; mi preocupación es el rendimiento percibido más que el rendimiento real (por ejemplo, tener una UI 100% sensible) todas las veces, incluso mientras se dibuja el "fondo", ya que hay superposiciones en ese búfer que podrían hacer que el usuario piense que la aplicación es más receptiva de lo que realmente es, al igual que lo hace un cursor, nunca se congela). –

+0

Sí, eso funciona, porque para Windows el dibujo no proviene de otro hilo;) – TomTom