2016-12-08 9 views
6

मैंने एक दिलचस्प समस्या में भाग लिया है। यह जानकर कि ConcurrentDictionary<TKey, TValue> संशोधित होने पर सुरक्षित रूप से गणना योग्य है, (मेरे मामले में) गायब हो जाने या कई बार प्रकट होने वाले तत्वों पर पुनरावृत्ति करने के अवांछित दुष्प्रभाव के साथ, मैंने ToList() का उपयोग करके स्वयं स्नैपशॉट बनाने का निर्णय लिया। चूंकि ConcurrentDictionary<TKey, TValue> भी ICollection<KeyValuePair<TKey, TValue>> लागू करता है, इस List(IEnumerable<T> collection) प्रयोग की जाने वाली है, जो बारी में शब्दकोश वर्तमान आइटम Count का उपयोग कर की वर्तमान आकार में एक सरणी बनाता है का कारण बनता है, तो using ICollection<T>.CopyTo(T[] array, int arrayIndex) आइटम पर कॉपी करने, अपने ConcurrentDictionary<TKey, TValue> कार्यान्वयन में बुला प्रयास करता है, और अंत में इस दौरान शब्दकोष में जोड़े जाने पर ArgumentException फेंकना।कॉलिंग टूलिस्ट() पर ConcurrentDictionary <TKey, TValue> आइटम जोड़ने के दौरान

सभी को लॉक करना संग्रह के उपयोग के बिंदु को मारने के बिंदु को मार देगा, इसलिए मेरे विकल्प अपवाद को पकड़ने और पुनः प्रयास करने के लिए प्रतीत होते हैं (जो निश्चित रूप से समस्या का सही उत्तर नहीं है), या मेरे लागू करने के लिए इस समस्या के लिए ToList() का स्वयं का संस्करण (लेकिन फिर, बस एक सूची बढ़ रही है, तो शायद कुछ तत्वों के लिए इसे सही आकार में ट्रिम करना एक ओवरकिल जैसा लगता है, और लिंक्डलिस्ट का उपयोग करके अनुक्रमण प्रदर्शन में कमी आएगी)।

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

क्या यह किसी समवर्ती संग्रह के साथ कोई समस्या हो सकती है?

इस तरह के स्नैपशॉट बनाने के दौरान प्रदर्शन को कम से कम हिट रखने के लिए उचित कार्यवाही क्या होगी? (अधिमानतः कुछ LINQ जादू के अंत में।)

संपादित करें:

इस पर ध्यान देने के बाद मुझे इस बात की पुष्टि कर सकते हैं, ToArray() (लगता है कि मैं सिर्फ कल यह द्वारा पारित) वास्तव में के रूप में स्नैपशॉट समस्या को हल करता है जब तक यह एक साधारण स्नैपशॉट है, यह तब मदद नहीं करता है जब स्नैपशॉट (जैसे फ़िल्टरिंग, सॉर्टिंग) लेने से पहले अतिरिक्त कार्यक्षमता की आवश्यकता होती है, और अंत में एक सूची/सरणी की आवश्यकता होती है। (इस मामले में, एक नया कॉल फिर से नया संग्रह बनाने की आवश्यकता है।)

मैं यह इंगित करने में असफल रहा कि स्नैपशॉट को इन संशोधनों के माध्यम से जाने की आवश्यकता हो सकती है या नहीं, इसलिए इसे लिया जाना चाहिए अंत में, अधिमानतः, इसलिए मैं इसे प्रश्नों में जोड़ दूंगा।

(इसके अलावा, अगर किसी को भी किसी शीर्षक के लिए एक बेहतर विचार है, बताऊँ।)

+2

'टोएएरे()' का उपयोग करें जो इसके बजाय विशेष रूप से प्रकार द्वारा लागू किया गया है। –

उत्तर

6

के जवाब देने हैं व्यापक ओवर-पीछा यहाँ सब समवर्ती प्रकार के लिए प्रश्न:

आप अलग हैं एक ऑपरेशन जो कई चरणों में आंतरिक से संबंधित है, जहां सभी चरणों को "सिंक में होना चाहिए", फिर हाँ, निश्चित रूप से आपको थ्रेड सिंक्रनाइज़ेशन के कारण क्रैश और विषम परिणाम मिलेंगे।

तो .ToList() का उपयोग कर पहले .Count के लिए पूछेंगे तो एक सरणी आकार, और फिर foreach का उपयोग सूची में मूल्यों और जगह हड़पने के लिए है, तो हाँ, निश्चित आप दो हिस्से मौका होगा अगर तत्वों की एक अलग संख्या प्राप्त करना।

ईमानदार होने के लिए मैं चाहता हूं कि उन समवर्ती प्रकारों में से कुछ ने नाटक करने की कोशिश नहीं की कि वे उन इंटरफेस को लागू करके सामान्य संग्रह थे लेकिन हां, ऐसा ही है।

क्या आप अपना कोड ठीक कर सकते हैं, अब आप इस मुद्दे के बारे में जानते हैं?

हाँ आप कर सकते हैं, आपको टाइप प्रलेखन पर एक नज़र डालना चाहिए और देखें कि क्या यह स्नैपशॉटिंग तंत्र का कोई भी रूप प्रदान करता है जो उपर्युक्त समस्याओं से ग्रस्त नहीं है।

एक नई सरणी System.Collections.Concurrent.ConcurrentDictionary से नकल कुंजी और मान जोड़ों का स्नैपशॉट युक्त

ConcurrentDictionary<TKey, TValue> औजार .ToArray(), जिसके साथ documented है बाहर कर देता है।

(मेरा जोर)

कैसे .ToArray() वर्तमान में कार्यान्वित किया जाता है?

Using locks, लाइन 697

देख तो अगर आप पूरे शब्दकोश ताला लगा स्नैपशॉट प्राप्त करना लग रहा है बहुत महंगी मैं इसकी सामग्री का एक स्नैपशॉट के साथ शुरू हथियाने का कार्य सवाल होता है।

साथ ही, .GetEnumerator() विधि, वही नियम से कुछ इस प्रकार documentation से:

प्रगणक शब्दकोश से लौटे सुरक्षित है पढ़ता है और शब्दकोश में लिखते हैं के साथ समवर्ती उपयोग करने के लिए, लेकिन यह करता है शब्दकोश के एक पल-इन-टाइम स्नैपशॉट का प्रतिनिधित्व नहीं करते हैं। एन्यूमेरेटर के माध्यम से उजागर सामग्री में GetEnumerator को कहा जाने के बाद शब्दकोश में किए गए संशोधनों में संशोधन हो सकता है।

(फिर से, मेरे emhpasis)

इसलिए जब .GetEnumerator()दुर्घटना नहीं है, यह परिणाम आप चाहते उत्पादन नहीं हो सकता होगा।

समय पर निर्भर करता है, न तो .ToArray(), तो यह सब निर्भर करता है।

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