2011-05-11 10 views
7

De acuerdo, en los formularios de Windows puede usar .refresh() para provocar un evento de redibujado en un elemento. ¿Hay una solución similar en WPF?WPF forzando el rediseño del lienzo

Una explicación de lo que estoy haciendo, estoy dibujando un laberinto en un objeto de lienzo, y me gustaría ver como se dibuja el laberinto (para que pueda ver el progreso) en lugar de esperar 28 minutos para encontrar una solución aparece de repente. Estoy dibujando bloques en el lienzo con una serie de Rectangle s. ¿Debería la actualización estar en el rectángulo o en el lienzo?

Aquí es una salida reciente: http://imgur.com/ftFOv

me gustaría una solución en C#, si eso es posible. Gracias.

Respuesta

7

Probablemente desee utilizar el objeto Dispatcher. Le sugiero que eche un vistazo a este artículo de Shawn Wildermuth: Build More Responsive Apps With The Dispatcher (revista MSDN de octubre de 2007).

+9

Esto no fue el 100% de la solución, pero me inició en la dirección correcta. Esto es en última instancia lo que funcionó: 'canvas.Dispatcher.Invoke (emptyDelegate, DispatcherPriority.Render);' donde emptyDelegate es 'Action emptyDelegate = delegate {};' – ohmusama

+0

Gracias, Simon, por la edición que hiciste hoy. Estoy leyendo el artículo ahora. – philologon

+2

El enlace a "Crear aplicaciones más receptivas con el despachador" ya no funciona. –

26

Esto es lo que busca ...

element.InvalidateVisual(); 
+0

Esto funciona bien, gracias @Adam – J3soon

11

este trabajo para mí ...

element.UpdateLayout(); 
2

Sin un buen Minimal, Complete, and Verifiable code example para mostrar claramente lo que está haciendo, es imposible para saber con certeza cuál es la mejor respuesta aquí. Sin embargo, según su descripción, parece que el algoritmo de generación de laberinto se está ejecutando en el hilo de la interfaz de usuario, lo que impide que la interfaz de usuario se actualice.

Al igual que en el caso de Windows Forms, donde las personas son tentadoras para llamar a métodos como Refresh() o Application.DoEvents(), el verdadero problema aquí es que estás bloqueando el hilo de interfaz de usuario. La forma correcta para arreglar que es, no hagas eso.

Hay muchas alternativas y sin una pregunta más detallada, no hay forma de saber cuál sería el mejor enfoque en su caso. Sin embargo, las dos técnicas más utilizadas y las más apropiadas son las de BackgroundWorker o Task.Run() en combinación con la clase Progress<T>. En cualquier caso, su algoritmo se ejecuta en un hilo diferente, pasando periódicamente actualizaciones al hilo de la interfaz de usuario (por ejemplo, cada rectángulo, cada diez rectángulos, lo que sea). El subproceso de la interfaz de usuario recibe una actualización, agrega los datos a las imágenes y luego vuelve a esperar la próxima actualización.

BackgroundWorker y Progress<T> ambos proporcionan mecanismos incorporados para organizar automáticamente los datos de vuelta a la secuencia de UI. La única advertencia es que cualquiera de esas clases que esté utilizando, la instancia de esa clase debe crearse en el hilo de la interfaz de usuario. Como deben configurarse antes de comenzar a ejecutar el trabajo asincrónico, esto normalmente no es un problema; viene gratis

Si lo haces de esta manera, no se necesita ningún hacks como los tres diferentes que se han sugerido aquí hasta ahora (dos de los cuales no parecen probable que sea aplicable en el "He bloqueado mi hilo de interfaz de usuario, ¿ahora qué? "escenario de todos modos).

Cuestiones relacionadas