84

我正在构建一个 Windows 应用商店应用程序,并且我有一些代码需要发布到 UI 线程。

为此,我想检索 CoreDispatcher 并使用它来发布代码。

似乎有几种方法可以做到这一点:

// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;

// Second way
Window.Current.Dispatcher;

我想知道哪一个是正确的?或者如果两者是等价的?

4

5 回答 5

153

这是首选方式:

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
    // Your UI update code goes here!
});

这样做的好处是它获得了主要CoreApplicationView功能,因此始终可用。更多细节在这里

您可以使用两种选择。

第一种选择

Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher

这将获取应用程序的活动视图,但如果没有激活任何视图,这将为您提供null 。更多细节在这里

第二种选择

Window.Current.Dispatcher

当从另一个线程调用此解决方案时,该解决方案将不起作用,因为它返回null而不是UI Dispatcher。更多细节在这里

于 2013-08-28T10:25:07.497 回答
16

对于使用 C++/CX 的任何人

Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
    CoreDispatcherPriority::Normal,
    ref new Windows::UI::Core::DispatchedHandler([this]()
{
    // do stuff
}));
于 2016-06-07T18:29:55.980 回答
2
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
            CoreDispatcherPriority.Normal,
            () => { // your code should be here});
于 2015-06-08T23:10:54.817 回答
1

虽然这是一个旧线程,但我想提请注意开发人员可能遇到的一个可能的问题,该问题影响了我并使得在大型 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% 的时间里,即使通过 QA 回归,一切都很好,但客户会时不时地报告问题。解决方案是包含下面的调用,而不是在实际页面中使用静态调用。

            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            { 

            });

当我需要确保从 App.xaml.cs 或我的 Singleton NavigationService 调用 UI 线程时,情况并非如此,后者处理推送/弹出到堆栈。当堆栈有各种从 MessageBus 触发的消息时,调度程序显然正在丢失调用哪个 UI 线程的跟踪,因为每个页面都有自己的 UI 线程。

希望这可以帮助其他可能受到影响的人,而且我认为每个平台都会通过发布一个涵盖最佳实践的完整项目来为他们的开发人员提供服务。

于 2019-12-11T22:57:40.310 回答
0

实际上,我会提出以下建议:

return (Window.Current == null) ? 
    CoreApplication.MainView.CoreWindow.Dispatcher : 
    CoreApplication.GetCurrentView().CoreWindow.Dispatcher

这样,如果您打开另一个视图/窗口,您就不会让调度程序感到困惑......

这个小宝石检查是否有一个窗口。如果没有,请使用 MainView 的 Dispatcher。如果有视图,请使用该视图的 Dispatcher。

于 2017-07-11T14:01:49.873 回答