विंडोज स्टोर ऐप में CoreDispatcher प्राप्त करने का सही तरीका


83

मैं एक विंडोज़ स्टोर ऐप बना रहा हूं, और मेरे पास कुछ कोड हैं जिन्हें यूआई थ्रेड में पोस्ट करने की आवश्यकता है।

उसके लिए, मैं CoreDispatcher को पुनः प्राप्त करना चाहूंगा और कोड को पोस्ट करने के लिए इसका उपयोग करूंगा।

ऐसा लगता है कि ऐसा करने के कुछ तरीके हैं:

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

// Second way
Window.Current.Dispatcher;

मुझे आश्चर्य है कि कौन सा सही है? या यदि दोनों बराबर हैं?


3
दोनों कर रहे हैं तरह सही का, लेकिन यह शून्य हो सकता है अगर आप इसे कुछ पहले से ही उस से एक्सेस करते नहीं कर रहे है डिस्पैचर के लिए उपयोग। यदि आप इसे एक ViewModel या नियंत्रक के रूप में उपयोग करना चाहते हैं, तो आपको डिस्पैचर को स्टोर करने की आवश्यकता होगी, आमतौर पर आपके App.xaml.cs या IOC नियंत्रक में एक स्थिर संपत्ति के रूप में, और इसे पहले पृष्ठ से सेट करें आपके पास भार है।
नैट डायमंड

जवाबों:


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

यह एप्लिकेशन के लिए सक्रिय दृश्य प्राप्त करता है, लेकिन यह आपको अशक्त कर देगा , यदि कोई दृश्य सक्रिय नहीं हुआ है। अधिक जानकारी यहाँ

दूसरा विकल्प

Window.Current.Dispatcher

जब यह UI डिस्पैचर के बजाय अशक्त हो जाता है तो यह समाधान किसी अन्य थ्रेड से कॉल करने पर काम नहीं करेगा । अधिक जानकारी यहाँ


मैंने यह कोशिश की, लेकिन जब मैं कोड का पता लगाता हूं, तो प्रतिनिधि कोड अभी भी एक वर्कर थ्रेड पर निष्पादित हो रहा है, न कि "मेन थ्रेड"।
राबर्ट ओस्क्लर

3
कृपया ध्यान दें कि (विंडोज 8.1 में कम से कम) डिस्पैचरप्रायोरिटी अब CoreDispatcherPriority
Illidan

2
यह तब तक काम करेगा जब तक हमारे पास एकल एएसटीए (एप्लिकेशन सिंगल-थ्रेडेड अपार्टमेंट) है। यदि हम "साझा लक्ष्य" सुविधा को पेश करते हैं, तो कई एएसटीए (प्रत्येक अपने स्वयं के डिस्पैचर के साथ) हैं। और फिर CoreApplication.MainView अशक्त हो सकता है (क्योंकि इसका एएसटीए अभी आरंभीकृत नहीं है)। जागरूक रहें!
यूरी शकटुला

मैंने CoreApplication देखा है। नैनोवाय थ्रेड से कॉल करने पर मेरा प्रोग्राम हैंग होने का कारण बनता है। मुझे बाद में इसे एक्सेस करने के लिए स्टार्टअप पर 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 है। यह Microsoft की Windows Runtime C ++ टेम्पलेट लाइब्रेरी (WRL) और C ++ / CX के लिए अनुशंसित प्रतिस्थापन है।" C ++ / WinRT
रिचर्ड चैम्बर्स

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;
    }
}

ऊपर से, मैंने डिस्पैचर को कॉल करने की अनुमति देने के लिए एक स्थिर वर्ग का उपयोग किया था - एक भी कॉल की अनुमति देने के लिए। 95% समय के लिए, क्यूए प्रतिगमन के माध्यम से भी सबकुछ ठीक था, लेकिन ग्राहक हर बार एक मुद्दे की रिपोर्ट करेंगे। इसका समाधान नीचे दिए गए कॉल को शामिल करना था, वास्तविक पृष्ठों में स्थिर कॉल का उपयोग नहीं करना।

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

            });

यह तब नहीं होता जब मुझे यह सुनिश्चित करने की आवश्यकता होती है कि UI थ्रेड को App.xaml.cs या मेरे सिंगलटन नेवीगेशन सर्विस से बुलाया गया था जो स्टैक पर पुश / पॉपिंग को नियंत्रित करता था। डिस्पैचर जाहिरा तौर पर यूआई थ्रेड का ट्रैक खो रहा था, क्योंकि प्रत्येक पृष्ठ का अपना यूआई थ्रेड होता है, जब स्टैक में मैसेजबस से विभिन्न प्रकार के संदेश ट्रिगर होते थे।

आशा है कि यह दूसरों को प्रभावित करने में मदद करता है और यह वह जगह भी है जहां मुझे लगता है कि प्रत्येक मंच अपने डेवलपर्स के लिए सर्वोत्तम प्रथाओं को कवर करने वाली एक पूरी परियोजना प्रकाशित करके एक सेवा करेगा।


0

वास्तव में, मैं इस की पंक्ति में कुछ प्रस्तावित करूंगा:

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

इस तरह, क्या आपको एक और दृश्य / विंडो खोलना चाहिए, आपको डिस्पैचर्स भ्रमित नहीं होंगे ...

यह छोटा रत्न जाँचता है कि क्या कोई विंडो भी है। यदि कोई नहीं है, तो MainView के डिस्पैचर का उपयोग करें। यदि कोई दृश्य है, तो उस डिस्पैचर का उपयोग करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.