GUI

2012-08-14 49 views
15

लॉक किए बिना बाध्य संग्रह में हजारों आइटम कैसे जोड़ें, मेरे पास एक सेटअप है जहां संभावित रूप से हजारों आइटम (3000-5000 सोचें) ObservableCollection में जोड़े जाएंगे जो कि कुछ दृश्य इंटरफ़ेस से बंधे हैं। वर्तमान में, उन्हें जोड़ने की प्रक्रिया काफी धीमी है (लगभग 4 सेकंड/1000 आइटम), और निश्चित रूप से उस समय के दौरान जीयूआई उत्तरदायी नहीं है। सिस्टम लॉकिंग के बारे में चिंता किए बिना कई वस्तुओं को एक संग्रह में ले जाने के लिए एक अच्छी विधि क्या है? मैंने DispatcherTimer पर देखा है, लेकिन मुझे यकीन नहीं है कि यह सब कुछ प्रदान करेगा जो मुझे चाहिए।GUI

एक और सवाल - क्या मैं इन वस्तुओं के निर्माण को तेज करने के लिए कुछ कर सकता हूं ताकि उन्हें संग्रह में जोड़ने में इतना समय लगे? वर्तमान में मैं उन्हें इस प्रकार उपयोग करता हूं: Collection.Add(new Item(<params>)) पहले से ही पृष्ठभूमि थ्रेड में, आइटमों को उत्पन्न करने से, उन्हें ध्यान देने योग्य राशि में जोड़ने के लिए समय कम हो जाता है?

संपादित करें: वर्चुअलाइजेशन संभव नहीं है। आवश्यकताओं, एक WrapPanel नज़र निर्दिष्ट इसलिए प्रदर्शन वास्तव में एक ListBox है जो है एक टेम्प्लेट की ItemsPanel

EDIT2: स्टॉपवॉच के अनुसार, टोंटी वास्तव में मेरे ObservableCollection में आइटम डाल रहा है। मैं उस संग्रह प्रकार को बदलने की कोशिश करूंगा और यह देखने के लिए अपनी खुद की अधिसूचना करूँगा कि क्या यह पर्याप्त रूप से गति करता है या नहीं।

संपादित 3: तो उत्तर एक ही स्थान पर है - मैंने ObservableCollection से प्राप्त कक्षा बनाने के द्वारा इस समस्या को हल किया है (नीचे से सहायता के साथ)। इस वर्ग ने दो चीजें की - एक समय में संग्रह जोड़ने के लिए एक विधि का पर्दाफाश किया, और CollectionChanged इवेंट को दबाने की क्षमता को जोड़ा। इन परिवर्तनों के साथ 3000 वस्तुओं को जोड़ने में लगने वाला समय मोटे तौर पर है। 4 सेकंड (9 7% सुधार)। This लिंक इन परिवर्तनों के कार्यान्वयन का विवरण देता है।

+1

कुछ ऐसी चीजें हैं जो आप कर सकते हैं। आपका पर्यवेक्षण चयन बनाने से पहले सभी ऑब्जेक्ट्स बनाना संभव हो सकता है, इस तरह, एक बार जब आप इसे बनाते हैं, तो आप इसे पहले से मौजूद वस्तुओं के संग्रह के साथ प्रारंभ कर सकते हैं। एक अन्य विकल्प [ReactiveExtensions] (http://msdn.microsoft.com/en-us/data/gg577609.aspx) का उपयोग कर रहा है जो आपको अपने डेटा स्रोत को "निरीक्षण" करने और आपके अवलोकननीय कोलेक्शन को अतुल्यकालिक रूप से जोड़ने की अनुमति देगा। – Thelonias

+0

इसके अलावा, यह आपके आइटम निर्माण के लिए होना चाहिए जो समय सिंक है, न कि "जोड़ें"। तो, क्या आप सृजन को किसी अन्य थ्रेड पर नहीं दबा सकते हैं, उन्हें कुछ मध्यवर्ती संग्रह में एकत्रित कर सकते हैं, और एक बार जब वे बनाए जाते हैं तो उन्हें GUI थ्रेड पर ऑब्जर्जेबल कोलेक्शन में जोड़ें? – Thelonias

+0

@Ryan ये कुछ अच्छे अंक हैं। मैं सृजन को पृष्ठभूमि में ले जाऊंगा और फिर अपनी गति की रिपोर्ट करूंगा। – steveg89

उत्तर

7

आप 1000 कहा है मद बनाने के लिए अनुमति देता है VirualizingStackPanel का उपयोग कर प्रदर्शन को बढ़ा सकते हैं, तो मुझे लगता है कि करने के लिए रह सकते हैं उदाहरण के लिए सिर्फ संख्या।

आईआईआरसी, अवलोकन संग्रह में एक छोटी सी कमी है - यदि आप एक-एक करके आइटम जोड़ते हैं, तो यह प्रत्येक आइटम के प्रति एक बार सूचित करता है। इसका मतलब है कि आपके पास 1000 आइटमों के लिए 1000 अधिसूचनाएं हैं और यूआई थ्रेड स्क्रीन को फिर से चलाने के लिए घातक गति से चलेंगे।

क्या आपको ASAP को फिर से निकालना होगा? शायद आप जोड़ों को बैच कर सकते हैं? 1000 वस्तुओं को 100 आइटमों के कुछ पैक, या 50 या 20 वस्तुओं के कुछ और पैकेट में विभाजित करें। फिर, सभी वस्तुओं को एक-एक करके रखने के बजाय, उन्हें पैकेट में रखें। लेकिन सावधान रहें: आपको कुछ तरीकों का उपयोग करना होगा जैसे कि संग्रह द्वारा लागू किए गए AddRange, स्वयं LINQ द्वारा नहीं, या फिर आपके पास एक-एक-एक प्रविष्टि होगी।यदि आपको ऐसी विधि मिलती है, तो इसे घटनाओं की संख्या में महत्वपूर्ण रूप से कटौती करनी चाहिए, क्योंकि संग्रह को प्रतिलिपि कॉल के बाद केवल एक बार परिवर्तित ईवेंट को बढ़ाया जाना चाहिए।

यदि देखने योग्य संग्रह में AddRange नहीं है, तो या तो अलग संग्रह का उपयोग करें, या अपना खुद का लिखें, केवल एक रैपर शायद पर्याप्त होगा। लक्ष्य प्रत्येक एकल ऐड() में परिवर्तित घटना को नहीं बढ़ाया जाना है, लेकिन उनकी उचित गणना के बाद, या - बस बढ़ाना छोड़ना जब आइटम जोड़े जाते हैं और उठाए जाते हैं तो कुछ नियमित समय अंतराल में बदल जाते हैं? यह फायदेमंद होगा, विशेष रूप से, यदि आपका डेटा स्थिर दर पर अनिश्चित काल तक "बहता है"।

बेशक, स्क्रीन पर आने वाली वस्तुओं की संख्या पर, आप इसे स्वयं प्रस्तुत करने पर भी हो सकते हैं। यदि आपके आइटम टेम्पलेट जटिल हैं, तो 1000 परतों के दृश्य दृश्य परतों/गुणों के 1000 उदाहरण उदाहरण उपयोगकर्ता अनुभव को मार सकते हैं। क्या आपने आइटम टेम्पलेट्स को न्यूनतम से सरल बना दिया है?

अंतिम बात: अपने आइटम नियंत्रण/सूची बॉक्स में आइटमपैनल्स के रूप में वर्चुअलाइजिंग स्टैकपैनल्स का उपयोग करने पर विचार करें। यह स्मृति पदचिह्न और एक बिंदु पर खींची गई वस्तुओं की संख्या को बहुत कम कर सकता है। यह आवश्यक संख्या या घटनाओं में जरूरी नहीं होगा, लेकिन जटिल आइटम टेम्पलेट्स होने पर यह बहुत मदद कर सकता है!

संपादित करें: आप ObservableCollection उपयोग कर रहे हैं, तो मैं WPF/Silverlight मान लिया गया है .. प्रश्न अपडेट करता है, तो यह सही

+0

हाँ, ओपी को अपना स्वयं का संग्रह बनाना होगा क्योंकि ObservableCollection AddRange को लागू नहीं करता है। संग्रहव्यू, आईआईआरसी का उपयोग करना संभव है, जो दृश्य को संग्रह को "रीफ्रेश" करने पर उपयोगकर्ता नियंत्रण प्रदान करेगा। – Thelonias

+0

मुझे एक रैपपैनल का उपयोग करने के लिए मजबूर किया गया है, इसलिए वर्चुअलाइजेशन तब तक संभव नहीं है जब तक कि मैं वर्चुअलाइज्डWrapPanel (जो वास्तव में मेरी सूची में कोशिश करने के लिए है) पर कुछ कोडप्रोजेक्ट प्रयासों का उपयोग नहीं करता है, इसलिए अब मैं गैर वर्चुअलाइज्ड आइटमों से फंस गया हूं। इस वजह से, मेरा टेम्पलेट उतना आसान है जितना मैं इन वस्तुओं के लिए बना सकता हूं। – steveg89

8

WPF Binding इस कारण से सहमति प्रदान करता है। Binding.IsAsync को सत्य पर सेट करने का प्रयास करें। के अतिरिक्त।

  • ObservableCollection<T> का उपयोग न करें, यह इसके लिए धीमा है क्योंकि प्रत्येक बार जब कोई आइटम जोड़ा जाता है तो यह घटनाओं को बढ़ाता है। List<T> जैसे कुछ तेज़ी से उपयोग करें और के बाद अपनी संपत्ति परिवर्तन अधिसूचना बढ़ाएं, आपके सभी आइटम जोड़े गए हैं।
  • पृष्ठभूमि आइटम में अपनी वस्तुओं को पूर्व-निर्माण करें, फिर उन्हें अपने संग्रह में दबाएं।
  • यह देखने के लिए कोड के अन्य हिस्सों की जांच करें कि क्या ब्लोट है, और ट्रिम करें।
+0

यहां तक ​​कि उस ध्वज सेट के साथ भी मुझे लगभग समान मात्रा में अंतराल मिलना जारी रहता है। ~ 12 सेकंड के लिए संग्रह संग्रह में जोड़े गए हैं – steveg89

+0

मेरा उत्तर अपडेट किया गया। –

+0

यहां अच्छे अंक भी हैं। मेरे पास अभी कोशिश करने के लिए कई चीजें हैं। धन्यवाद। – steveg89

0
दूसरा सवाल के लिए

अगर आपके जीयूआई में आप WPF प्रौद्योगिकियों का उपयोग कर रहे हैं, तो आप आप ही दिखाई

+0

मैं यह समझाने के लिए अपनी मूल पोस्ट संपादित करूंगा कि यह क्यों संभव नहीं है। – steveg89

4

एक और बात तुम कोशिश कर सकते नहीं है: उपवर्ग ObservableCollection और इसे समर्थन थोक लोड हो रहा है बनाने के (AddRange) । यहां एक आलेख है: AddRange and ObservableCollection

+0

यह मेरा मार्ग होने का अंत हो सकता है। मैंने पहले से ही 'ऑब्जर्जेबल कोलेक्शन' उपclassed है, लेकिन बेस एड (जिसे 1000 बार कहा जाता है) एड लूप में बिताए गए अधिकांश समय खा रहा है। – steveg89

+0

आप पृष्ठभूमि थ्रेड से AddRange को कॉल करने का प्रयास कर सकते हैं, और यूआई थ्रेड पर ऑब्जर्जेबल कोलेक्शन प्रेषण ऑनकॉलेक्शन चेंज कॉल का कार्यान्वयन कर सकते हैं। (AFAIR संग्रहChanged घटना WPF बाध्यकारी द्वारा यूआई थ्रेड को स्वचालित रूप से प्रेषित नहीं किया गया है) – Volma

+0

आपकी टिप्पणी ने मुझे सही दिशा में इंगित किया और मुझे एक समाधान ढूंढने दिया जो पूरी तरह कार्यान्वित किया गया था। विवरण के लिए मेरा संपादन देखें। मुझे अभी भी उस व्यक्ति को श्रेय देना है जो पहले विचार को सामने लाया था। – steveg89

4

अनुरोध करके, मैंने इस मुद्दे को हल किया है। मैंने एक कक्षा बनाकर शुरू किया जो ObservableCollection से विरासत में मिलता है। इस वर्ग ने दो चीजें की - पूरे संग्रह को एक साथ जोड़ने के लिए एक विधि का पर्दाफाश किया, और CollectionChanged इवेंट को दबाने की क्षमता को जोड़ा। इन परिवर्तनों के साथ 3000 वस्तुओं को जोड़ने में लगने वाला समय मोटे तौर पर है। 4 सेकंड (9 7% सुधार)। This लिंक इन परिवर्तनों के कार्यान्वयन का विवरण देता है।