2011-12-15 35 views
6

En mi aplicación wpf, se llama a una operación que consume mucho tiempo en mi viewmodel usando un subproceso independiente. Esta función, sin embargo, accede a varias propiedades en el modelo de vista que están vinculadas a objetos en la vista. Traté de acceder a ellos directamente y no veo quejas sobre que sean propiedad del hilo de la interfaz de usuario. Estoy interesado en conocer las consecuencias de usarlos directamente entre hilos.Acceso a las propiedades de ViewModel desde un subproceso diferente

+0

¿Está cambiando el 'ViewModel' o simplemente leerlo hilos separados? – SliverNinja

+0

solo hilos separados – Aks

Respuesta

5

Puede usar su ViewModel desde cualquier hilo, incluidos la lectura y la escritura. La única excepción principal es tratar con colecciones: las colecciones vinculadas a datos deben escribirse en el subproceso de la interfaz del usuario, ya que el enlace no se asigna automáticamente al hilo de la interfaz de usuario (como lo hacen los enlaces simples).

Sin embargo, aún debe considerar tener una sincronización adecuada para cualquier escritura. Se producirán problemas normales de sincronización de subprocesos, ya que ViewModel es solo otra clase.

Habiendo dicho esto, normalmente, querrá manejar la sincronización de forma ligeramente diferente de lo que haría en muchos casos. Normalmente, los bloqueos no funcionan en un ViewModel, ya que el enlace de datos WPF no bloqueará los objetos. Como tal, normalmente debería usar Dispatcher.Invoke/BeginInvoke para coordinar las llamadas al hilo de la interfaz de usuario según sea necesario cuando se requiera sincronización en ViewModel.

+0

Como, por ejemplo, si tengo un 'ToggleButton' vinculado a un' bool' en la máquina virtual. Y estoy haciendo un 'if (bool)' en un hilo separado, ¿qué tendré que hacer para mantener la sincronización aquí para que no exista conflicto entre el usuario que configura el alternar y la condición if que se está ejecutando? – Aks

+0

@Aks No. Si solo está leyendo un valor como ese, no tendrá problemas. Dicho esto, probablemente (técnicamente) marque el bool volátil. Para obtener detalles, consulte: http://stackoverflow.com/questions/458173/can-ac-sharp-thread-really-cache-a-value-and-ignore-changes-to-that-value-on-ot/458193 # 458193 –

1

No hay consecuencias aparte de sus preocupaciones de seguridad de hilos habituales. Lo único que generalmente es problemático con las propiedades de VM es ObservableCollections que tienen afinidad por el hilo.

+0

Si tuviera que usar bloqueos, ¿no es probable que el hilo de la interfaz de usuario se cuelgue? – Aks

+0

Esto es cierto, pero las "preocupaciones de seguridad de subprocesos habituales" tienden a requerir soluciones inusuales, ya que WPF ignorará cualquier bloqueo o sincronización de subprocesos estándar que intente utilizar. –

0

Si utiliza ampliar su ObservableCollection con esto, se puede actualizar desde un hilo separado:

/// <summary> 
/// Source: New Things I Learned 
/// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView 
/// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx 
/// Note: Improved for clarity and the following of proper coding standards. 
/// </summary> 
/// <param name="e"></param> 
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
{ 
    // Use BlockReentrancy 
    using (BlockReentrancy()) 
    { 
     var eventHandler = CollectionChanged; 

     // Only proceed if handler exists. 
     if (eventHandler != null) 
     { 
      Delegate[] delegates = eventHandler.GetInvocationList(); 

      // Walk thru invocation list 
      foreach (NotifyCollectionChangedEventHandler handler in delegates) 
      { 
       var currentDispatcher = handler.Target as DispatcherObject; 

       // If the subscriber is a DispatcherObject and different thread 
       if ((currentDispatcher != null) && 
        (currentDispatcher.CheckAccess() == false)) 
       { 
        // Invoke handler in the target dispatcher's thread 
        currentDispatcher.Dispatcher.Invoke(
         DispatcherPriority.DataBind, handler, this, e); 
       } 

       else 
       { 
        handler(this, e); 
       } 
      } 
     } 
    } 
} 

/// <summary> 
/// Overridden NotifyCollectionChangedEventHandler event. 
/// </summary> 
public override event NotifyCollectionChangedEventHandler CollectionChanged; 
Cuestiones relacionadas