2010-03-04 14 views
35

Estoy compilando una aplicación WPF. Estoy haciendo una comunicación asíncrona con el lado del servidor, y utilizo la agregación de eventos con Prism en el cliente. Ambas cosas dan como resultado que se engendren nuevos hilos que no son el hilo de UI. Si intento hacer "operaciones WPF" en estos hilos de devolución de llamada y manejador de eventos, el mundo se derrumbará, lo que ahora ha comenzado a hacer.Asegurándome de que todo se ejecute en el subproceso UI en WPF

Primero encontré problemas al tratar de crear algunos objetos WPF en la devolución de llamada desde el servidor. Me dijeron que el hilo necesitaba ejecutarse en modo STA. Ahora estoy tratando de actualizar algunos datos UI en un controlador de eventos Prism, y me dijeron que:

El llamante no puede acceder a este hilo porque lo posee un hilo diferente.

So; ¿Cuál es la clave para hacer las cosas bien en WPF? He leído en el Despachador de WPF en this MSDN post. Estoy empezando a obtenerlo, pero todavía no soy un mago.

  1. es la clave para utilizar siempre Dispatcher.Invoke cuando necesito para ejecutar algo que no estoy seguro de que será llamado en el subproceso de interfaz de usuario?
  2. ¿Importa si realmente se llamó en el hilo de la interfaz de usuario, y lo hago Dispatcher.Invoke de todos modos?
  3. Dispatcher.Invoke = sincrónico. Dispathcher.BeginInvoke = async?
  4. Will Dispatcher.Invoke solicita el hilo de UI y luego se detiene para esperarlo? ¿Es una mala práctica y el riesgo de programas menos receptivos?
  5. ¿Cómo obtengo el despachador de todos modos? Will Dispatcher.CurrentDispatcher siempre me da el despachador que representa el hilo de UI?
  6. ¿Existirá más de un despachador, o es "Dispatcher" básicamente el mismo que el subproceso de interfaz de usuario para la aplicación?
  7. ¿Y cuál es el problema con BackgroundWorker? ¿Cuándo uso esto en su lugar? ¿Supongo que esto siempre es asincrónico?
  8. ¿Todo lo que se ejecuta en el subproceso de la interfaz de usuario (al ser invocado) se ejecutará en el modo de apartamento STA? Es decir. si tengo algo que requiera que se ejecute en modo STA, ¿será suficiente Dispatcher.Invoke?

¿Alguien quiere aclarar las cosas para mí? ¿Alguna recomendación relacionada, etc.? ¡Gracias!

Respuesta

37

El pasar cada una de sus preguntas, una por una:

    No
  1. bastante; solo debe invocar en el subproceso de interfaz de usuario cuando sea necesario. Ver # 2.
  2. Sí, importa. No debe simplemente Invoke automáticamente todo. La clave es invocar solo en el subproceso de interfaz de usuario si es necesario. Para hacer esto, puede usar el método Dispatcher.CheckAccess.
  3. Eso es correcto.
  4. También es correcto, y sí, corres el riesgo de programas menos receptivos. La mayoría de las veces, no se verá un golpe de rendimiento severo (estamos hablando de milisegundos para un cambio de contexto), pero solo debería ser Invoke si es necesario. Dicho esto, en algunos puntos es inevitable, entonces no, no diría que es una mala práctica. Es solo una solución a un problema que encontrarás de vez en cuando.
  5. En todos los casos que he visto, lo he hecho con Dispatcher.CurrentDispatcher. Para escenarios complejos, esto puede no ser suficiente, pero yo (personalmente) no los he visto.
  6. No del todo correcto, pero esta línea de pensamiento no hará ningún daño. Permítanme ponerlo de esta manera: el Dispatcherse puede utilizar para obtener acceso a el subproceso de interfaz de usuario para la aplicación. Pero no es en sí mismo el hilo de UI.
  7. BackgroundWorker se usa generalmente cuando tiene una operación que consume mucho tiempo y desea mantener una interfaz de usuario receptiva mientras se ejecuta esa operación en segundo plano. Normalmente no utiliza BackgroundWorker en lugar de de Invoke, sino que utiliza BackgroundWorker junto con Invoke. Es decir, si necesita actualizar algún objeto UI en su BackgroundWorker, puede invocar en el hilo de la interfaz de usuario, realizar la actualización y luego volver a la operación original.
  8. Sí. El hilo de la interfaz de usuario de una aplicación WPF, por definición, debe ejecutarse en un apartamento de subproceso único.

Hay mucho que decir sobre BackgroundWorker, estoy seguro de que muchas preguntas ya están dedicadas a él, así que no entraré en demasiada profundidad. Si tienes curiosidad, echa un vistazo al MSDN page for BackgroundWorker class.

+0

Muchas gracias Charlie! ¡Esto es realmente esclarecedor y útil! – stiank81

+0

Agregó una 8va pregunta a la lista. Espero que puedas actualizar tu respuesta para incluirla :-) – stiank81

+0

Haha editado para responder a tu pregunta final. – Charlie

Cuestiones relacionadas