2009-08-18 9 views
7

Tengo una tarea que puede realizar mi GUI que extraerá información para llenar un ViewModel con una respuesta de consulta de base de datos SQL. Supongamos que quiero comenzar esta tarea y mantener mi GUI libre para continuar con otras cosas, y mientras tanto reproducir una animación de "búsqueda", ¿cuál es la manera correcta de hacer esto en WPF/MVVM? Supongo que debe iniciar un proceso asincrónico y establecer un bool vinculado a un activador de datos que inicie el guión gráfico de la animación. ¿Pero qué uso para comenzar el proceso? ¿Hilo? Todavía soy nuevo en WPF y solo quiero asegurarme de estar usando las clases correctas disponibles para mí.Forma correcta en WPF MVVM para iniciar una tarea de búsqueda con subprocesos

Respuesta

8

Uso el hilo BackgroundProcess para hacer cosas como esta.

Aquí hay un enlace a MSDN en esto: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

detalles adicionales relacionados con este.

Tiene tres EVENTOS asociados con su objeto BackgroundProcess: DoWork, ReportProgress y WorkCompleted.

Ahora, para usar esto y para usarlo con una colección observable, querrá decirle al objeto BackgroundProcess que pueda INFORMAR PROGRESO (esta es una propiedad booleana que siempre establecí explícitamente, junto con el permite la cancelación).

Ahora, para comenzar un proceso, llamará al método RunWorkerAsync. Este método tiene la capacidad de aceptar una variable OBJECT en caso de que necesite pasar datos (si desea más de 1 valor, cree una estructura para pasarla a RunWorkerAsync).

RunWorkerAsync activa el evento DoWork, por lo que controla el controlador de eventos DoWork. Aquí está (desinfectados) código desde donde estoy utilización de la misma:

Dim dt As System.Data.DataTable 
dt = da.GetDataTable(sql, System.Data.CommandType.Text, params) 
For Each row As System.Data.DataRow In dt.Rows 
    If loadQuestionsWorker.CancellationPending Then 
     e.Cancel = True 
     Exit Sub 
    End If 
    Dim item As New DataObject 
    // Assign Item Values 
    backgroundProcessObject.ReportProgress(1, item) 
Next 

lo que está pasando aquí, es que estoy un tabla de datos de mi capa de datos y, a continuación, mientras que este backgroundprocess no se está cancelando, estoy caminando por la tabla de datos, y cuando construyo un nuevo DataObject, informo que ese objeto está siendo construido.

Ahora, en mi controlador de eventos ProgressChanged (el método ReportProgress plantea la ProgressChanged evento) de control está de vuelta en las manos del hilo de interfaz de usuario para que pueda hacer cosas como el impacto de la interfaz de usuario y añadir el elemento que estoy informando sobre un ObservableCollection.

Finalmente, en mi controlador de eventos WorkedCompleted (cuyo evento correspondiente se produce cuando el método del controlador de eventos DoWork se ejecuta), verifico si mi progreso fue cancelado (lo que a veces significa que deseo volcar el ObservableCollection) y yo puede o no afectar la interfaz de usuario (por ejemplo, la eliminación de una "búsqueda" de animación.

+0

intentado esto, parece encerrar a My Tho interfaz gráfica de usuario ... – Firoso

+0

si se bloquea su interfaz gráfica de usuario que está haciendo mal. –

+0

lo estaba haciendo mal, fui a hilo, mirando esto sin embargo realmente me gusta esto. – Firoso

2

puede iniciar una nueva Thread o BackgroundWorker explícitamente, o utilizar un ThreadPool. no estoy al tanto de cualquier forma recomendada de hacer esto en MVVM ...

Si su operación asincrónica está rellenando un ObservableCollection vinculado a un control, tenga en cuenta que no puede agregar artículos a ella en un hilo diferente. Debes hacerlo en el hilo del despachador del control. O también se puede utilizar this collection, lo que provoca el evento CollectionChanged en la rosca adecuada

+0

Creo que estoy teniendo un problema relacionado aquí con la colección Observable, mi código está basado en MVVM y mi trabajador está haciendo cambios en el modelo de vista ... ese modelo de vista está vinculado a los elementos de la interfaz de usuario ... por lo que se está bloqueando . – Firoso

+0

El enlace en propiedades escalares funciona bien en los subprocesos, la notificación de cambio se organiza automáticamente en el subproceso correcto. Para colecciones, no es compatible. Mira el enlace que te di para una posible solución –

1
var t = new Thread((ThreadStart)delegate 
{ 
    DoWork(...) 
    Dispatcher.BeginInvoke((Action)delegate 
    { 
      SomethingOntheUiThread(...) 
      FinishedWork(...); 
    } 
}); 

t.Start(); 
Cuestiones relacionadas