Я создаю приложение Windows Store, и у меня есть код, который нужно опубликовать в потоке пользовательского интерфейса.
Для этого я хотел бы получить CoreDispatcher и использовать его для публикации кода.
Похоже, есть несколько способов сделать это:
// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
// Second way
Window.Current.Dispatcher;
Интересно, какой из них правильный? или если оба эквивалентны?
c#
windows-runtime
windows-store-apps
async-await
dispatcher
лизергиновая кислота
источник
источник
Ответы:
Это предпочтительный способ:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Your UI update code goes here! });
Преимущество этого в том, что он становится основным
CoreApplicationView
и всегда доступен. Подробнее здесь .Есть две альтернативы, которые вы можете использовать.
Первая альтернатива
Это получает активное представление для приложения, но это даст вам значение null , если никакие представления не были активированы. Подробнее здесь .
Вторая альтернатива
Это решение не будет работать, когда оно вызывается из другого потока, так как оно возвращает null вместо UI Dispatcher . Подробнее здесь .
источник
Для всех, кто использует C ++ / CX
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() { // do stuff }));
источник
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { // your code should be here});
источник
Хотя это старый поток, я хотел привлечь внимание к возможной проблеме, с которой могут столкнуться разработчики, которая повлияла на меня и чрезвычайно затруднила отладку в больших приложениях UWP. В моем случае я реорганизовал следующий код из приведенных выше предложений еще в 2014 году, но время от времени меня мучили случайные зависания приложений, которые были случайными по своей природе.
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; } }
Исходя из вышеизложенного, я использовал статический класс, чтобы разрешить вызов Dispatcher по всему приложению, что позволило выполнить один вызов. В 95% случаев все было хорошо даже при регрессии контроля качества, но клиенты время от времени сообщали о проблеме. Решение заключалось в том, чтобы включить вызов ниже, не используя статический вызов на реальных страницах.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { });
Это не тот случай, когда мне нужно убедиться, что поток пользовательского интерфейса был вызван из App.xaml.cs или моего Singleton NavigationService, который обрабатывал нажатие / всплытие в стек. Диспетчер явно не отслеживал, какой поток пользовательского интерфейса был вызван, поскольку каждая страница имеет свой собственный поток пользовательского интерфейса, когда в стеке было множество сообщений, запускаемых из MessageBus.
Надеюсь, это поможет другим, которые могут быть затронуты, и я думаю, что именно здесь каждая платформа окажет услугу своим разработчикам, опубликовав полный проект, охватывающий лучшие практики.
источник
Собственно, я бы предложил что-то вроде этого:
return (Window.Current == null) ? CoreApplication.MainView.CoreWindow.Dispatcher : CoreApplication.GetCurrentView().CoreWindow.Dispatcher
Таким образом, если вы откроете еще один вид / окно, вы не запутаете диспетчеров ...
Эта маленькая жемчужина проверяет, есть ли вообще Окно. Если нет, используйте диспетчер MainView. Если есть представление, используйте его Диспетчер.
источник