Tworzę aplikację Windows Store i mam kod, który należy opublikować w wątku interfejsu użytkownika.
W tym celu chciałbym pobrać CoreDispatcher i użyć go do wysłania kodu.
Wygląda na to, że można to zrobić na kilka sposobów:
// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
// Second way
Window.Current.Dispatcher;
Zastanawiam się, który z nich jest poprawny? lub jeśli oba są równoważne?
c#
windows-runtime
windows-store-apps
async-await
dispatcher
kwas lizergowy
źródło
źródło
Odpowiedzi:
To jest preferowany sposób:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Your UI update code goes here! });
Zaletą tego jest to, że pobiera główny
CoreApplicationView
i jest zawsze dostępny. Więcej szczegółów tutaj .Istnieją dwie alternatywy, z których możesz skorzystać.
Pierwsza alternatywa
Spowoduje to pobranie aktywnego widoku aplikacji, ale da ci to wartość zerową , jeśli żadne widoki nie zostały aktywowane. Więcej szczegółów tutaj .
Druga alternatywa
To rozwiązanie nie będzie działać, gdy jest wywoływane z innego wątku, ponieważ zwraca wartość null zamiast Dispatcher interfejsu użytkownika . Więcej szczegółów tutaj .
źródło
Dla każdego, kto używa C ++ / CX
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { // do stuff }));
źródło
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { // your code should be here});
źródło
Chociaż jest to stary wątek, chciałem zwrócić uwagę na możliwy problem, z którym mogą się spotkać programiści, który wpłynął na mnie i bardzo utrudnił debugowanie w dużych aplikacjach UWP. W moim przypadku w 2014 roku przerobiłem poniższy kod z powyższych sugestii, ale od czasu do czasu nękany był przez sporadyczne zawieszanie się aplikacji, które miało charakter losowy.
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; } }
Z powyższego korzystałem z klasy statycznej, aby umożliwić wywołanie Dispatchera w całej aplikacji - pozwalając na pojedyncze wywołanie. W 95% przypadków wszystko było w porządku, nawet przy regresji kontroli jakości, ale klienci od czasu do czasu zgłaszali problem. Rozwiązaniem było dołączenie wywołania poniżej, bez używania wywołania statycznego na rzeczywistych stronach.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { });
Nie dzieje się tak, gdy muszę upewnić się, że wątek interfejsu użytkownika został wywołany z App.xaml.cs lub mojej usługi Singleton NavigationService, która obsługiwała wypychanie / wyskakiwanie na stos. Dyspozytor najwyraźniej tracił informacje o tym, który wątek interfejsu użytkownika został wywołany, ponieważ każda strona ma swój własny wątek interfejsu użytkownika, gdy stos miał różne komunikaty wyzwalane z MessageBus.
Mam nadzieję, że pomoże to innym, na których może to mieć wpływ, i myślę, że jest to również miejsce, w którym każda platforma świadczyłaby usługę swoim programistom, publikując kompletny projekt obejmujący najlepsze praktyki.
źródło
Właściwie zaproponowałbym coś w tym stylu:
return (Window.Current == null) ? CoreApplication.MainView.CoreWindow.Dispatcher : CoreApplication.GetCurrentView().CoreWindow.Dispatcher
W ten sposób, gdybyś otworzył inny Widok / Okno, nie pomylisz dyspozytorów ...
Ten mały klejnot sprawdza, czy jest nawet okno. Jeśli nie ma, użyj Dispatcher MainView. Jeśli jest widok, użyj tego Dyspozytora.
źródło