2009-10-29 8 views
60

मैंने हाल ही में WPF में प्रोग्रामिंग शुरू कर दी है और निम्न समस्या में टक्कर लगी है। मुझे समझ में नहीं आता कि Dispatcher.Invoke() विधि का उपयोग कैसे करें। मैं सूत्रण में अनुभव है और मैं कुछ सरल विंडोज फॉर्म्स कार्यक्रमों जहां मैं सिर्फDispatcher का उपयोग कर गैर-मुख्य धागे से WPF नियंत्रण बदलें। इन्वोक

Control.CheckForIllegalCrossThreadCalls = false; 

इस्तेमाल किया हाँ मुझे पता है कि बहुत लंगड़ा लेकिन इन सरल निगरानी अनुप्रयोगों थे बना दिया है।

तथ्य यह है कि अब मैं एक WPF एप्लिकेशन बना रहा हूं जो पृष्ठभूमि में डेटा पुनर्प्राप्त करता है, मैं डेटा को पुनर्प्राप्त करने के लिए कॉल करने के लिए एक नया धागा शुरू करता हूं (वेबसर्वर से), अब मैं इसे अपने डब्ल्यूपीएफ पर प्रदर्शित करना चाहता हूं प्रपत्र। बात यह है कि, मैं इस धागे से कोई नियंत्रण नहीं लगा सकता। एक लेबल या कुछ भी नहीं। इसे कैसे हल किया जा सकता है?

उत्तर टिप्पणियां:
@Jalfp:
तो मैं 'नए चलने' में इस डिस्पैचर विधि का उपयोग करें जब मैं डेटा प्राप्त? या क्या मुझे पृष्ठभूमि कार्यकर्ता डेटा को पुनर्प्राप्त करना चाहिए, इसे एक फ़ील्ड में रखना चाहिए और एक नया धागा शुरू करना चाहिए जो इस फ़ील्ड भरने तक प्रतीक्षा करता है और प्रेषक को नियंत्रण में पुनर्प्राप्त डेटा दिखाने के लिए कॉल करता है?

उत्तर

145

पहली बात यह समझना है कि डिस्पैचर को लंबे अवरोधन ऑपरेशन (जैसे वेबसेवर से डेटा पुनर्प्राप्त करने के लिए ...) चलाने के लिए डिज़ाइन नहीं किया गया है। जब आप एक ऑपरेशन चलाने के लिए चाहते हैं तो आप डिस्पैचर का उपयोग कर सकते हैं जो UI थ्रेड पर निष्पादित किया जाएगा (जैसे प्रगति पट्टी के मान को अपडेट करना)।

पृष्ठभूमि कार्यकर्ता में अपना डेटा पुनर्प्राप्त करने और UI थ्रेड में परिवर्तनों को प्रसारित करने के लिए ReportProgress विधि का उपयोग करने के लिए आप क्या कर सकते हैं।

तुम सच में सीधे डिस्पैचर उपयोग करने के लिए की जरूरत है, यह बहुत सरल है:

Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => this.progressBar.Value = 50)); 
+19

आप 'नए कार्रवाई (' भाग से छुटकारा पा सकते हैं, और बस एक लैम्ब्डा अभिव्यक्ति का उपयोग: 50 – jrista

+0

हाँ नहीं जानते DispatcherPriority.Background,() => this.progressBar.Value = कारण है कि मैं एक डाल यहां क्रिया: पी – japf

+0

तो जब मैं डेटा प्राप्त करता हूं तो क्या मैं इस डिस्पैचर विधि को 'नया ट्रेड' में उपयोग करता हूं? या क्या मुझे पृष्ठभूमि कार्यकर्ता डेटा को पुनर्प्राप्त करना चाहिए, इसे एक फ़ील्ड में रखना चाहिए और एक नया थ्रेड शुरू करना चाहिए जो इस फ़ील्ड तक प्रतीक्षा करता है पुनर्प्राप्त डेटा को नियंत्रण में दिखाने के लिए प्रेषक को भर दिया और कॉल किया? –

19

japf इसे सही ढंग से जवाब देने के है। अगर आप बहु-पंक्ति क्रियाओं को देख रहे हैं, तो आप नीचे लिख सकते हैं।

Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => { 
    this.progressBar.Value = 50; 
    })); 

अन्य उपयोगकर्ताओं को, जो प्रदर्शन के बारे में जानना चाहता हूँ के लिए सूचना:

अपने कोड की जरूरत उच्च प्रदर्शन के लिए लिखे जाने की, तो आपको पहले जांच कर सकते हैं आह्वान CheckAccess ध्वज का उपयोग कर के लिए आवश्यक है।

if(Application.Current.Dispatcher.CheckAccess()) 
{ 
    this.progressBar.Value = 50; 
} 
else 
{ 
    Application.Current.Dispatcher.BeginInvoke(
     DispatcherPriority.Background, 
     new Action(() => { 
     this.progressBar.Value = 50; 
     })); 
} 

ध्यान दें कि विधि CheckAccess() विजुअल स्टूडियो 2015 से छिपा हुआ है तो बस IntelliSense उम्मीद कर यह दिखाने अप करने के लिए बिना यह लिखें। ध्यान दें कि चेकएप पर प्रदर्शन पर ओवरहेड है (कुछ नैनोसेकंड में ओवरहेड)। यह केवल तब बेहतर होता है जब आप किसी भी कीमत पर 'invoke' करने के लिए आवश्यक माइक्रोक्रॉन्ड को सहेजना चाहते हैं। साथ ही, कॉलिंग विधि सुनिश्चित करते समय दो तरीकों (इनवॉक के साथ, और अन्य बिना) बनाने का विकल्प हमेशा होता है यदि यह यूआई थ्रेड में है या नहीं। जब आप प्रेषक के इस पहलू को देखना चाहते हैं तो यह दुर्लभ मामला है।

संबंधित मुद्दे