C# 在 Windows Store 应用程序中获取 CoreDispatcher 的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16477190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:06:30  来源:igfitidea点击:

Correct way to get the CoreDispatcher in a Windows Store app

c#windows-runtimewindows-store-appsasync-awaitdispatcher

提问by lysergic-acid

I'm building a Windows Store app, and I have some code that needs to be posted to the UI thread.

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

For that, i'd like to retrieve the CoreDispatcher and use it to post the code.

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

It seems that there are a few ways to do so:

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

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

// Second way
Window.Current.Dispatcher;

I wonder which one is correct? or if both are equivalent?

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

采纳答案by MAXE

This is the preferred way:

这是首选方式:

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

The advantage this has is that it gets the main CoreApplicationViewand so is always available. More details here.

这样做的优点是它获得了主要内容CoreApplicationView,因此始终可用。更多细节在这里

There are two alternatives which you could use.

您可以使用两种替代方法。

First alternative

第一个选择

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

This gets the active view for the app, but this will give you null, if no views has been activated. More details here.

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

Second alternative

第二种选择

Window.Current.Dispatcher

This solution will not work when it's called from another thread as it returns nullinstead of the UI Dispatcher. More details here.

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

回答by apramc

await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
            CoreDispatcherPriority.Normal,
            () => { // your code should be here});

回答by Brett Pennings

For anyone using C++/CX

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

Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
    CoreDispatcherPriority::Normal,
    ref new Windows::UI::Core::DispatchedHandler([this]()
{
    // do stuff
}));

回答by J. H.

Actually, I would propose something in the line of this:

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

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

That way, should you have openend another View/Window, you won't get the Dispatchers confused...

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

This little gem checks whether there is even a Window. If none, use the MainView's Dispatcher. If there is a view, use that one's Dispatcher.

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

回答by Dave Friedel

While this is an old thread, I wanted to draw attention to a possible issue developers may run across which impacted me and made it extremely difficult to debug in large UWP apps. In my case, I refactored the following code from the suggestions above back in 2014 but would occasionally be plagued with the occasional app freezes that were random in nature.

虽然这是一个旧线程,但我想提请注意开发人员可能遇到的一个可能的问题,该问题影响了我并使在大型 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;
    }
}

From the above, I had used a static class to allow the calling of the Dispatcher through-out the application - allowing for a single call. For 95% of the time, everything was fine even through QA regression but clients would report an issue every now and then. The solution was to include the call below, not using a static call in the actual pages.

从上面可以看出,我使用了一个静态类来允许在整个应用程序中调用 Dispatcher - 允许单个调用。在 95% 的时间里,即使通过 QA 回归,一切都很好,但客户会时不时地报告一个问题。解决方案是包含下面的调用,而不是在实际页面中使用静态调用。

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

            });

This is not the case when I need to ensure the UI Thread was called from App.xaml.cs or my Singleton NavigationService which handled pushing/popping on to the stack. The dispatcher apparently was losing track of which UI Thread was called, since each page has it's own UI thread, when the stack had a variety of Messages triggering from the MessageBus.

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

Hope this helps others that may be impacted and it is also where I think each platform would do a service to their developers by publishing a complete project covering the best practices.

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