Windows 스토어 앱에서 CoreDispatcher를 가져 오는 올바른 방법


83

Windows 스토어 앱을 구축 중이며 UI 스레드에 게시해야하는 코드가 있습니다.

이를 위해 CoreDispatcher를 검색하여 코드를 게시하는 데 사용하고 싶습니다.

이를 수행하는 몇 가지 방법이있는 것 같습니다.

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

// Second way
Window.Current.Dispatcher;

어느 것이 맞습니까? 또는 둘 다 동등하다면?


3
둘은 종류의 올바른의,하지만 당신은 이미 무언가에서 액세스하지 않는 경우는 null가됩니다 있다 디스패처에 액세스 할 수 있습니다. 예를 들어 ViewModel 또는 Controller에서 사용하려면 Dispatcher에서 일반적으로 App.xaml.cs 또는 IOC 컨트롤러의 정적 속성으로 저장하고 첫 번째 페이지에서 설정해야합니다. 부하가 있습니다.
Nate Diamond

답변:


148

이것이 선호되는 방법입니다.

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

이 솔루션은 UI Dispatcher 대신 null 을 반환하므로 다른 스레드에서 호출 될 때 작동하지 않습니다 . 자세한 내용은 여기를 참조 하세요 .


나는 이것을 시도했지만 코드를 추적 할 때 위임 코드는 여전히 "주 스레드"가 아닌 작업자 스레드에서 실행됩니다.
Robert Oschler 2014

3
(적어도 Windows 8.1에서는) DispatcherPriority는 이제 CoreDispatcherPriority
Illidan

2
이것은 단일 ASTA (응용 프로그램 단일 스레드 아파트)가있는 한 작동합니다. "공유 대상"기능을 도입하는 경우 여러 ASTA (각각 자체 디스패처가있는 ASTA)가 있습니다. 그리고 CoreApplication.MainView는 null이 될 수 있습니다 (ASTA가 아직 초기화되지 않았기 때문에). 조심하세요!
Yury Schkatula

CoreApplication.MainView로 인해 UI가 아닌 스레드에서 호출 될 때 프로그램이 중단되는 것을 보았습니다. 나중에 액세스하려면 시작할 때 CoreApplication.MainView.CoreWindow.Dispatcher를 숨겨야했습니다.
sjb-sjb

15

C ++ / CX를 사용하는 모든 사람

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

1
"C ++를 사용하여 Windows 런타임 API를 작성하고 사용하는 경우 C ++ / WinRT가 있습니다. 이것은 Windows 런타임 C ++ 템플릿 라이브러리 (WRL) 및 C ++ / CX에 대한 Microsoft의 권장 대체품입니다." C ++ / WinRT
Richard Chambers

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

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, () =>
            { 

            });

이는 UI 스레드가 App.xaml.cs 또는 스택에 대한 푸시 / 팝을 처리 한 내 Singleton NavigationService에서 호출되었는지 확인해야하는 경우가 아닙니다. 디스패처는 스택에 MessageBus에서 트리거되는 다양한 메시지가있을 때 각 페이지에 자체 UI 스레드가 있기 때문에 어떤 UI 스레드가 호출되었는지 추적하지 못하고있었습니다.

이것이 영향을받을 수있는 다른 사람들에게 도움이되기를 바라며 각 플랫폼이 모범 사례를 다루는 전체 프로젝트를 게시하여 개발자에게 서비스를 제공 할 것이라고 생각합니다.


0

사실, 나는 이것의 라인에서 무언가를 제안 할 것입니다.

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

이렇게하면 다른보기 / 창을 열면 Dispatcher가 혼동되지 않습니다.

이 작은 보석은 창이 있는지 확인합니다. 없는 경우 MainView의 Dispatcher를 사용하십시오. 보기가 있으면 해당 Dispatcher를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.