2011-06-30 12 views
5

Me está costando un tiempo descifrar cómo manejar un subproceso de una clase fuera de mi ViewModel.Cómo manejar el subproceso de C# WPF en el modelo de vista de MVVM

El subproceso se origina de una clase Track. Aquí está el código ResponseEventHandler en Track:

public delegate void ResponseEventHandler(AbstractResponse response); 
public event ResponseEventHandler OnResponseEvent; 

Cuando un método de "comando" se procesa a partir de dentro de mi objeto Track, el siguiente código corre el OnResponseEvent, que envía un mensaje en un hilo de vuelta a mi modelo de vista:

if (OnResponseEvent != null) 
{ 
    OnResponseEvent(GetResponseFromCurrentBuffer()); 
} 

GetResponseFromCurrentBuffer() meramente devuelve un tipo de mensaje que es un tipo predefinido dentro del Track.

Mi MainWindowViewModel constructor crea un controlador de eventos para el OnResponseEvent del Track:

public MainWindowViewModel() 
{ 
    Track _Track = new Track(); 

    _Track.OnResponseEvent += 
     new Track.ResponseEventHandler(UpdateTrackResponseWindow); 
} 

Por lo tanto, la idea es que cada vez que tengo un mensaje nuevo procedente de la OnResponseEvent hilo, que ejecuta el método UpdateTrackResponseWindow(). Este método añadirá una nueva cadena de mensajes a una propiedad ObservableCollection<string> lista llamada TrackResponseMessage:

private void UpdateTrackResponseWindow(AbstractResponse message) 
{ 
    TrackResponseMessage.Add(FormatMessageResponseToString(message)); 
} 

FormatMessageResponseToString() El método se limita a comparar el mensaje con todos los tipos de mensajes predefinidos dentro de la Track, y hace algo de formato de cadena ingenioso.

El problema principal es: La interfaz de usuario desaparece cuando se ejecuta TrackResponseMessage.Add(). El ejecutable todavía se está ejecutando en segundo plano, y la única manera de terminar la tarea es cerrar Visual Studio 2010.

TrackResponseMessage es una propiedad pública dentro de mi modelo de vista:

public ObservableCollection<String> TrackResponseMessage 
{ 
    get { return _trackResponseMessage; } 
    set 
    { 
     _trackResponseMessage = value; 
     RaisePropertyChanged("TrackResponseMessage"); 
    } 
} 

¿Hay una necesidad de yo para ordenar el Thread que proviene del objeto Track a mi ViewModel? ¡Cualquier código de ejemplo sería muy apreciado!

Respuesta

9

¿Hay una necesidad para mí para ordenar el hilo que viene desde el objeto Track.cs a mi viewmodel? ¡Cualquier código de ejemplo sería muy apreciado!

Sí. Desafortunadamente, aunque INotifyPropertyChanged manejará eventos de otros hilos, INotifyCollectionChanged no (es decir, ObservableCollection<T>). Como tal, debes volver a la máquina virtual.

Si la VM se está creando desde la Vista (MVVM Vista-Primero) o se sabe que se creó en el subproceso UI, hay una buena opción para usar.NET 4 tareas:

TaskScheduler uiScheduler; 
public MainWindowViewModel() 
{ 
    uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
    Track _Track = new Track(); 
    _Track.OnResponseEvent += new Track.ResponseEventHandler(UpdateTrackResponseWindow); 
} 

Luego, más tarde, el controlador de eventos puede hacer:

private void UpdateTrackResponseWindow(AbstractResponse message) 
{ 
    Task.Factory.StartNew(
     () => TrackResponseMessage.Add(FormatMessageResponseToString(message)), 
     CancellationToken.None, TaskCreationOptions.None, 
     uiScheduler); 
} 

Esto tiene la buena ventaja de no tirar de WPF o Silverlight recursos y tipos específicos en su clase ViewModel (es decir: Dispatcher), sin dejar de ofrecer todos los beneficios. También funciona, sin cambios, en otras rutinas con afinidad de subprocesos (es decir, trabajo de servicio WCF).

+0

Yeeehaw !! ¡Funcionó muy bien! Reed, ¡te debo una dona! Me salvaste horas leyendo la documentación de enhebrar .net. TaskScheduler facilita la lectura de subprocesos entrantes de otros objetos de clase en mi viewmodel. – EnLaCucha

+0

@EnLaCucha: FYI - Esto solo funciona para hilos que tienen instalado SynchronizationContext. Eso es cierto para el hilo principal de WPF, el hilo principal de WinForms y las llamadas de servicio WCF. –

+0

Con .NET 4.5 ahora puede editar colecciones de otro hilo usando BindingOperations.EnableCollectionSynchronization https://msdn.microsoft.com/en-us/library/hh140164(v=vs.110).aspx – Kelly

0

Si RaisePropertychanged se ejecuta en un hilo que no sea el hilo de la interfaz de usuario Y el controlador de eventos para el evento toca la interfaz de usuario, debe cambiar al hilo de la interfaz de usuario.

Cuestiones relacionadas