Estoy creando una aplicación de la Tienda Windows y tengo un código que debe publicarse en el hilo de la interfaz de usuario.
Para eso, me gustaría recuperar el CoreDispatcher y usarlo para publicar el código.
Parece que hay algunas formas de hacerlo:
// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
// Second way
Window.Current.Dispatcher;
Me pregunto cuál es la correcta. o si ambos son equivalentes?
c#
windows-runtime
windows-store-apps
async-await
dispatcher
ácido lisérgico
fuente
fuente
Respuestas:
Esta es la forma preferida:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Your UI update code goes here! });
La ventaja que tiene esto es que obtiene el principal
CoreApplicationView
y, por tanto, siempre está disponible. Más detalles aquí .Hay dos alternativas que puede utilizar.
Primera alternativa
Esto obtiene la vista activa para la aplicación, pero esto le dará nulo , si no se ha activado ninguna vista. Más detalles aquí .
Segunda alternativa
Esta solución no funcionará cuando se llame desde otro hilo, ya que devuelve un valor nulo en lugar de UI Dispatcher . Más detalles aquí .
fuente
Para cualquiera que use C ++ / CX
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { // do stuff }));
fuente
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { // your code should be here});
fuente
Si bien este es un hilo antiguo, quería llamar la atención sobre un posible problema que los desarrolladores pueden encontrar, lo que me impactó y dificultó enormemente la depuración en aplicaciones de UWP grandes. En mi caso, refactoricé el siguiente código de las sugerencias anteriores en 2014, pero ocasionalmente estaba plagado de congelamientos ocasionales de aplicaciones que eran de naturaleza aleatoria.
public static class DispatcherHelper { public static Task RunOnUIThreadAsync(Action action) { return RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, action); } public static async Task RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority priority, Action action) { try { await returnDispatcher().RunAsync(priority, () => { action(); }); } catch (Exception ex) { var noawait = ExceptionHandler.HandleException(ex, false); } } private static Windows.UI.Core.CoreDispatcher returnDispatcher() { return (Windows.UI.Xaml.Window.Current == null) ? CoreApplication.MainView.CoreWindow.Dispatcher : CoreApplication.GetCurrentView().CoreWindow.Dispatcher; } }
De lo anterior, había usado una clase estática para permitir la llamada del Dispatcher en toda la aplicación, lo que permite una sola llamada. Durante el 95% del tiempo, todo estuvo bien incluso a través de la regresión de control de calidad, pero los clientes informaban un problema de vez en cuando. La solución fue incluir la llamada a continuación, no usar una llamada estática en las páginas reales.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { });
Este no es el caso cuando necesito asegurarme de que se llamó al subproceso de la interfaz de usuario desde App.xaml.cs o mi Singleton NavigationService que manejó empujar / hacer estallar en la pila. El despachador aparentemente estaba perdiendo la pista de qué subproceso de la interfaz de usuario se llamó, ya que cada página tiene su propio subproceso de la interfaz de usuario, cuando la pila tenía una variedad de mensajes que se activaban desde MessageBus.
Espero que esto ayude a otros que puedan verse afectados y también es donde creo que cada plataforma haría un servicio a sus desarrolladores al publicar un proyecto completo que cubra las mejores prácticas.
fuente
En realidad, propondría algo en la línea de esto:
return (Window.Current == null) ? CoreApplication.MainView.CoreWindow.Dispatcher : CoreApplication.GetCurrentView().CoreWindow.Dispatcher
De esa manera, si ha abierto otra Vista / Ventana, no confundirá a los Despachadores ...
Esta pequeña joya comprueba si incluso hay una ventana. Si no hay ninguno, use el Dispatcher de MainView. Si hay una vista, use el Dispatcher de esa.
fuente