2010-05-13 15 views
6

तक पहुंचने वाले विभिन्न धागे में कुछ कोड है जो मेमोरीस्ट्रीम ऑब्जेक्ट को डेटा को GetBuffer() पर कॉल करके सीधे डेटा बफर में लिखता है। यह स्थिति और SetLength() गुणों का उचित रूप से उपयोग और अद्यतन करता है।मेमोरीस्ट्रीम

यह कोड सही समय 99.9 999% काम करता है। सचमुच। केवल हर 100,000 पुनरावृत्तियों में यह बार-बार होगा। विशिष्ट समस्या यह है कि मेमोरीस्ट्रीम की स्थिति संपत्ति अचानक उचित मान के बजाय शून्य लौटाती है।

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

ठीक है। जाहिर है, यह एक थ्रेडिंग मुद्दा होना चाहिए। और सबसे अधिक संभावना एक संकलक अनुकूलन मुद्दा।

हालांकि, इस सॉफ़्टवेयर की प्रकृति यह है कि यह शेड्यूलर के साथ "कार्यों" द्वारा व्यवस्थित है और इसलिए किसी भी वास्तविक ओ/एस थ्रेड में से कोई भी इस कोड को किसी भी समय चला सकता है - लेकिन कभी भी एक से अधिक नहीं पहर।

तो मेरा अनुमान है कि आम तौर पर ऐसा होता है कि एक ही थ्रेड इस विधि के लिए उपयोग करता रहता है और फिर दुर्लभ अवसर पर एक अलग धागा का उपयोग किया जाता है। (थ्रेड आईडी को कैप्चर और तुलना करके इस सिद्धांत का परीक्षण करने के लिए बस विचार करें।)

फिर कंपाइलर अनुकूलन के कारण, अलग-अलग धागे को सही मान कभी नहीं मिलता है। यह एक "पुराना" मूल्य हो जाता है।

आमतौर पर इस तरह की स्थिति में मैं चरम पर एक "अस्थिर" कीवर्ड लागू करता हूं यह देखने के लिए कि क्या यह ठीक करता है। लेकिन इस मामले में चर मेमोरीस्ट्रीम ऑब्जेक्ट के अंदर हैं।

क्या किसी के पास कोई अन्य विचार है? या इसका मतलब यह है कि हमें अपनी मेमोरीस्ट्रीम ऑब्जेक्ट को कार्यान्वित करना है?

निष्ठा से, वेन

संपादित करें: बस एक परीक्षण है जो इस विधि के लिए कॉल की कुल संख्या में गिना जाता है और समय की संख्या ManagedThreadId आखिरी कॉल की तुलना में अलग है मायने रखता भाग गया। यह लगभग 50% समय है कि यह थ्रेड स्विच करता है - उनके बीच वैकल्पिक। तो ऊपर मेरा सिद्धांत लगभग निश्चित रूप से गलत है या त्रुटि कहीं अधिक होती है।

संपादित करें: यह बग इतना ही कम होता है कि किसी भी आत्मविश्वास को महसूस करने से पहले बग के बिना चलाने में लगभग एक सप्ताह लग जाएगा, यह वास्तव में चला गया है। इसके बजाए, समस्या की प्रकृति की पुष्टि करने के लिए प्रयोगों को चलाने के लिए बेहतर है।

संपादित करें: वर्तमान में लॉकिंग को मेमोरीस्ट्रीम का उपयोग करने वाले 5 तरीकों में से प्रत्येक में लॉक() कथन के माध्यम से संभाला जाता है।

+0

तुल्यकालन आपरेशन सभी स्मृति अपने उपयोगकर्ता के अंतरिक्ष चर के लिए सही अर्थ विज्ञान सुनिश्चित करने के लिए बाधाओं को आह्वान। आपको 'अस्थिर' की आवश्यकता नहीं है। कुछ और गलत है। –

उत्तर

5

(वास्तव में यह पुष्टि करने के लिए आदर्श कोड की जरूरत है।)

MemoryStream सदस्यों सुरक्षित धागा के रूप में दस्तावेज नहीं कर रहे हैं (उदाहरण के लिए Position) ताकि आप आप केवल इस उदाहरण (या तार्किक एक एक वस्तु के लिए किसी भी संदर्भ का उपयोग कर रहे हैं सुनिश्चित करने की आवश्यकता एक समय में एक थ्रेड से MemoryStream का हिस्सा)। तो आप इस तरह के एक पहुँच के रूप में लंबे समय के रूप में एक अलग धागा — से एक उदाहरण का उपयोग कर सकते

लेकिन MemoryStream, नहीं धागा आत्मीयता होने के रूप में प्रलेखित है समवर्ती नहीं है।

थ्रेडिंग (इस क्यू & एक के लिए स्वयंसिद्ध) कठिन है।

मैं सुझाव दूंगा कि आपके पास कुछ समवर्ती पहुंच चल रही है, दोनों थ्रेड दोनों एक ही उदाहरण को एक साथ एक्सेस करते हैं और कभी-कभी, उदाहरण स्थिति के कुछ पहलू को दूषित करते हैं।

मैं यह सुनिश्चित करना होगा मैं ताला यथासंभव सरल रखने के लिए और काम कर बातें (अतिरिक्त चालाक बनने की कोशिश कर और लॉकिंग सीमित अक्सर कीड़े खोजने के लिए बहुत मुश्किल का कारण है)। बहु-कोर सिस्टम पर परीक्षण करने से भी मदद मिल सकती है। केवल प्रोफाइलिंग को आज़माएं और ऑप्टिमाइज़ करें यदि प्रोफ़ाइल दिखाती है कि महत्वपूर्ण नेट (संपूर्ण रूप से आवेदन) लाभ की संभावना है।

+0

मदद करने की कोशिश करने के लिए बहुत बहुत धन्यवाद! ऊपर मेरे संपादन देखें। इसके अलावा, मैं एक प्रयोग वर्तमान में जो एक "countThreads" चर जो एक अपवाद फेंकता countThreads> 1. इस तर्क संपत्ति डाटा नामित जिसके कारण अन्य वस्तुओं MemoryStream का उपयोग लपेटता यदि का एक interlocked.increment और घटती का उपयोग करता है। कभी नहीं फिसल गया हो जाता है यही कारण है यही वजह है कि ऐसा लगता है कि केवल एक ही धागा शामिल है। हालांकि, कक्षा के भीतर विधियां केवल "डेटा" वर्ग फ़ील्ड का उपयोग करती हैं। मैं उन सभी को संशोधित कर रहा हूँ भी डाटा संपत्ति का उपयोग करने के अगर 2 धागे हर पहुँच यह देखने के लिए एक साथ। – Wayne

+0

उपर्युक्त टिप्पणी साबित हुई कि आप सही थे। डेटा संपत्ति को दो अलग-अलग थ्रेड से एक्सेस किया जा रहा था। मैं खोज के लिए इस तकनीक का सुझाव देता हूं। वास्तव में कोड को लिखने के लिए कोड लिखें जब 2 धागे कॉल करें और प्रत्येक से स्टैक ट्रेस प्राप्त करें। वही मैंने किया। तब यह पता चला की वजह से एक अलग थ्रेड शुरू हुआ एक टीसीपी/आईपी सॉकेट से शेष बाइट्स बाहर साफ करने के लिए किया जाना है। यही कारण है कि यह बहुत दुर्लभ था। यह केवल एक सॉकेट समापन प्रक्रिया के दौरान होने का मौका था। – Wayne

+0

क्षमा करें। सोचा था कि यह तय किया गया था लेकिन यह दोहराया गया। यह मुद्दा केवल समस्या का एक हिस्सा था। मेमोरीस्ट्रीम को कभी-कभी शून्य स्थिति मिलती है, भले ही किसी थ्रेड टकराव के लिए असंभव न हो। मैं सभी तरीकों अधिरोहित और एक अस्थिर स्थान और लंबाई चर जो क्योंकि के बाद से MSDN डॉक्स का कहना है कि MemoryStream सुरक्षित थ्रेड नहीं है केवल शेष मुद्दा है को शामिल किया है, वे शायद इसका मतलब यह भी जब संकलन संकलक अनुकूलन के कारण कुछ धागा संबंध है कि रिलीज मोड में। अगर दूसरों के लाभ के लिए समस्या हल हो जाती है तो मैं कुछ दिनों के बाद पोस्ट करूंगा। – Wayne

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