2011-01-07 10 views
15

Digamos que en un entorno MVVM, estoy en un hilo de fondo y me gustaría ejecutar una actualización en un control ui. Normalmente iría a myButton.Dispatcher.BeginInvoke (blabla) pero no tengo acceso a myButton (porque el modelo de vista no tiene acceso a los controles de la vista). Entonces, ¿cuál es el patrón normal para hacer esto?WPF/Multithreading: UI Dispatcher en MVVM

(supongo que siempre hay unión, pero me gustaría saber cómo hacerlo a través de la operadora)

+2

Duplicado de http://stackoverflow.com/questions/486758/is-wpf-dispatcher-the-solution-of-multi-threading-problems? –

+0

No es un duplicado ... pregunta cómo obtener un despachador de un hilo de fondo iniciado por un ViewModel (que normalmente no tiene acceso a un despachador). –

Respuesta

36

lo general el uso Application.Current.Dispatcher: ya es Application.Current estático, no necesita una referencia a un control

+7

¿Y cómo probará usted sus modelos de vista sin un objeto de aplicación? –

+2

@Geert van Horrik Puede burlarse del objeto de la aplicación para probar sus modelos de vista en unidades. Perdón por el comentario del necro. Acabo de tropezar con este artículo de SO mientras buscaba una solución MVVM válida para la programación multiproceso. – SRM

0

Se podría provocar un evento en su Ver Modelo (tal vez utilizando una convención de nomenclatura para indicar que va a surgir de un hilo que no sea UI, por ejemplo NotifyProgressChangedAsync). A continuación, su Vista a quién está unido al evento puede tratar con el despachador de manera apropiada.

O bien, podría pasar un delegado a una función de sincronización a su Modelo de Vista (desde su Vista).

13

De Caliburn Micro código fuente:

public static class Execute 
{ 
    private static Action<System.Action> executor = action => action(); 

    /// <summary> 
    /// Initializes the framework using the current dispatcher. 
    /// </summary> 
    public static void InitializeWithDispatcher() 
    { 
#if SILVERLIGHT 
     var dispatcher = Deployment.Current.Dispatcher; 
#else 
     var dispatcher = Dispatcher.CurrentDispatcher; 
#endif 
     executor = action =>{ 
      if(dispatcher.CheckAccess()) 
       action(); 
      else dispatcher.BeginInvoke(action); 
     }; 
    } 

    /// <summary> 
    /// Executes the action on the UI thread. 
    /// </summary> 
    /// <param name="action">The action to execute.</param> 
    public static void OnUIThread(this System.Action action) 
    { 
     executor(action); 
    } 
} 

Antes de su utilización, usted tendrá que llamar Execute.InitializeWithDispatcher() desde el hilo de interfaz de usuario a continuación, se puede utilizar de esta manera Execute.OnUIThread(()=>SomeMethod())

+0

Todavía obtengo el error si uso Dispatcher.CurrentDispatcher. Funciona correctamente si uso Application.Current.Dispatcher. –

0

Pase el despachador del subproceso de la interfaz de usuario al constructor de ViewModel y guárdelo en la máquina virtual.

Tenga en cuenta que cada hilo puede tener su propio despachador. ¡Necesitarás el hilo de la interfaz de usuario!

4

La ViewModelBase de Catel tiene una propiedad de Dispatcher que puede usar.

+0

Método GetCurrentDispatcher en la clase DispatcherHelper.https://catel.codeplex.com/SourceControl/latest#src/Catel.MVVM/Catel.MVVM.NET40/Windows/Threading/Helpers/Dispatcherhelper.cs –

4

Tiendo a que mis ViewModels hereden de DependencyObject y me aseguren de que estén construidos en el hilo de la interfaz de usuario, lo que los hace perfectamente para manejar esta situación: tienen una propiedad Dispatcher que corresponde al despachador del subproceso de la interfaz de usuario. Entonces, no necesita contaminar su vista con los detalles de implementación de ViewModel.

Algunas otras ventajas:

  • la capacidad de prueba de unidad: Usted puede probar la unidad de éstos sin una aplicación en ejecución (en lugar de depender de Application.Current.Dispatcher)
  • acoplamiento débil entre Vista & modelo de vista
  • Puede definir las propiedades de dependencia en su ViewModel y no escriba ningún código para actualizar la vista a medida que cambian esas propiedades.
Cuestiones relacionadas