Estou construindo um aplicativo da Windows Store e tenho alguns códigos que precisam ser postados no thread de interface do usuário.
Para isso, gostaria de recuperar o CoreDispatcher e usá-lo para postar o código.
Parece que existem algumas maneiras de fazer isso:
// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
// Second way
Window.Current.Dispatcher;
Eu me pergunto qual é o correto? ou se ambos são equivalentes?
c#
windows-runtime
windows-store-apps
async-await
dispatcher
ácido lisérgico
fonte
fonte
Respostas:
Esta é a forma preferida:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Your UI update code goes here! });
A vantagem disso é que ele obtém o principal
CoreApplicationView
e está sempre disponível. Mais detalhes aqui .Existem duas alternativas que você pode usar.
Primeira alternativa
Isso obtém a visualização ativa do aplicativo, mas resultará em nulo , se nenhuma visualização tiver sido ativada. Mais detalhes aqui .
Segunda alternativa
Esta solução não funcionará quando for chamada de outro thread, pois retorna nulo em vez do UI Dispatcher . Mais detalhes aqui .
fonte
Para qualquer pessoa que use C ++ / CX
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { // do stuff }));
fonte
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { // your code should be here});
fonte
Embora este seja um tópico antigo, eu queria chamar a atenção para um possível problema que os desenvolvedores podem encontrar e que me impactou e tornou extremamente difícil depurar em grandes aplicativos UWP. No meu caso, refatorei o código a seguir a partir das sugestões acima em 2014, mas ocasionalmente era atormentado por congelamentos ocasionais de aplicativos que eram de natureza aleatória.
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; } }
Do exposto acima, usei uma classe estática para permitir a chamada do Dispatcher por todo o aplicativo - permitindo uma única chamada. Em 95% do tempo, tudo estava bem, mesmo com a regressão do controle de qualidade, mas os clientes relatavam um problema de vez em quando. A solução foi incluir a chamada abaixo, não usando uma chamada estática nas páginas reais.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { });
Este não é o caso quando eu preciso garantir que o UI Thread foi chamado de App.xaml.cs ou meu Singleton NavigationService que manipulou push / popping na pilha. O despachante aparentemente estava perdendo o controle de qual UI Thread foi chamado, uma vez que cada página tem seu próprio UI thread, quando a pilha tinha uma variedade de Mensagens disparadas do MessageBus.
Espero que isso ajude outras pessoas que possam ser afetadas e também é onde eu acho que cada plataforma prestaria um serviço aos seus desenvolvedores, publicando um projeto completo cobrindo as melhores práticas.
fonte
Na verdade, eu proporia algo nesta linha:
return (Window.Current == null) ? CoreApplication.MainView.CoreWindow.Dispatcher : CoreApplication.GetCurrentView().CoreWindow.Dispatcher
Dessa forma, se você abrir outra Visualização / Janela, não confundirá os Dispatchers ...
Esta pequena joia verifica se há uma janela. Se nenhum, use o Dispatcher do MainView. Se houver uma visualização, use o Dispatcher dessa.
fonte