c# - Cambie los controles WPF de un hilo no principal utilizando Dispatcher.Invoke
multithreading (2)
Lo primero es comprender que el Dispatcher no está diseñado para ejecutar operaciones de bloqueo prolongadas (como recuperar datos de un servidor web ...). Puede usar Dispatcher cuando desee ejecutar una operación que se ejecutará en el hilo de la interfaz de usuario (por ejemplo, actualizar el valor de una barra de progreso).
Lo que puede hacer es recuperar sus datos en un trabajador en segundo plano y usar el método ReportProgress para propagar los cambios en el hilo de la interfaz de usuario.
Si realmente necesita usar el Dispatcher directamente, es bastante simple:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => this.progressBar.Value = 50));
Recientemente comencé a programar en WPF y me topé con el siguiente problema. No entiendo cómo usar el método Dispatcher.Invoke()
. Tengo experiencia en enhebrar y he hecho algunos programas simples de Windows Forms donde acabo de usar el
Control.CheckForIllegalCrossThreadCalls = false;
Sí, sé que es bastante cojo, pero estas fueron simples aplicaciones de monitoreo.
El hecho es que ahora estoy haciendo una aplicación WPF que recupera datos en segundo plano, comienzo un nuevo hilo para hacer la llamada para recuperar los datos (desde un servidor web), ahora quiero mostrarlos en mi formulario WPF. La cuestión es que no puedo establecer ningún control desde este hilo. Ni siquiera una etiqueta ni nada. ¿Como puede ésto ser resuelto?
Responda los comentarios:
@Jalfp:
Entonces, ¿utilizo este método Dispatcher en la ''nueva banda de rodadura'' cuando obtengo los datos? ¿O debería hacer que un trabajador de fondo recupere los datos, los coloque en un campo y comience un nuevo hilo que espere hasta que se llene este campo y llame al despachador para mostrar los datos recuperados en los controles?
japf ha respondido correctamente. En caso de que estés mirando acciones de varias líneas, puedes escribir lo siguiente.
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
Información para otros usuarios que desean saber sobre el rendimiento:
Si su código NECESITA escribirse para un alto rendimiento, primero puede verificar si se requiere la invocación mediante el uso del indicador CheckAccess.
if(Application.Current.Dispatcher.CheckAccess())
{
this.progressBar.Value = 50;
}
else
{
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => {
this.progressBar.Value = 50;
}));
}
Tenga en cuenta que el método CheckAccess () está oculto de Visual Studio 2015, así que simplemente escríbalo sin esperar que lo muestre intellisense. Tenga en cuenta que CheckAccess tiene una sobrecarga en el rendimiento (sobrecarga en pocos nanosegundos). Solo es mejor cuando desea guardar ese microsegundo requerido para realizar la ''invocación'' a cualquier costo. Además, siempre hay una opción para crear dos métodos (activado con invocación y otro sin) cuando el método de llamada es seguro si está en UI Thread o no. Es raro que ocurra un caso raro cuando debería estar mirando este aspecto del despachador.