2012-04-11 10 views
7

के साथ मेरे पास मेरे .NET 3.5 C# WinForms एप्लिकेशन में एक कक्षा है जिसमें पांच विधियां हैं। प्रत्येक विधि सी ++ COM इंटरफेस के विभिन्न सेट का उपयोग करती है। इन COM ऑब्जेक्ट्स को साफ़ करने के लिए Marshal.FinalReleaseCOMObject का उपयोग कर रहा हूं। यह कोड किसी भी मुद्दे के बिना इस .NET मंच पर ठीक काम करता है। लेकिन जब मैं .NET 4.0 के लिए इस आवेदन ले जाते हैं, मैं एक पंक्ति है, जहां मैं ICOMInterface2 को ICOMInterface1 से एक चर डाली पर इन तरीकों में से एक में यह त्रुटि मिलती, यानी शुरू:"COM ऑब्जेक्ट जिसे इसके अंतर्निहित आरसीडब्ल्यू से अलग किया गया है, का उपयोग नहीं किया जा सकता" .NET 4.0

ICOMInterface1 myVar= obj as ICOMInterface2; 

COM वस्तु है इसके अंतर्निहित आरसीडब्ल्यू से अलग किया गया नहीं किया जा सकता है।

और यदि मैं Marshal.FinalReleaseCOMObject का उपयोग कर लाइन को हटा देता हूं, तो मुझे यह त्रुटि नहीं मिलती है।

मुझे यहां क्या याद आ रही है? और मैं .NET 4.0 प्लेटफ़ॉर्म पर स्मृति से इन अप्रबंधित COM ऑब्जेक्ट्स को कैसे साफ़ करूं?

उत्तर

13

सरल उत्तर कभीMarshal.FinalReleaseComObject का उपयोग करें जब तक कि आपको बिल्कुल जरूरी न हो। और यदि आप करते हैं, तो कुछ अतिरिक्त नियम हैं जिनका आपको पालन करना होगा।

जब कोई COM ऑब्जेक्ट .NET में उपयोग किया जाता है, तो रनटाइम उस ऑब्जेक्ट के लिए "आरसीडब्ल्यू" या "रनटाइम कॉल करने योग्य रैपर" के रूप में जाना जाता है। यह आरसीडब्ल्यू सिर्फ एक सामान्य वस्तु है जो वस्तु पर एक COM संदर्भ रखती है। जब यह ऑब्जेक्ट कचरा इकट्ठा होता है, तो यह COM ऑब्जेक्ट पर IU अज्ञात :: रिलीज़() को कॉल करेगा, जैसा कि आप उम्मीद करेंगे। इसका मतलब यह नहीं है कि जब तक आपकी COM ऑब्जेक्ट को की आवश्यकता होती है कि अंतिम रिलीज() समय पर एक बहुत ही निश्चित पल पर किया जाता है, तो कचरा कलेक्टर इसका ख्याल रखे। कई COM ऑब्जेक्ट्स इस मामले में आते हैं, इसलिए पूरी तरह से सत्यापित करें कि आप कॉल को रिलीज़() सावधानी से प्रबंधित करें।

तो जब आप FinalReleaseComObject को कॉल कर रहे हैं, तो यह अनिवार्य रूप से आरसीडब्ल्यू को COM ऑब्जेक्ट पर संदर्भ में कमी कर रहा है जब तक यह शून्य हिट नहीं हो जाता है और आरसीडब्ल्यू फिर COM ऑब्जेक्ट को जारी करता है। इस बिंदु पर, यह आरसीडब्ल्यू अब ज़ोंबीड है, और इसका कोई भी उपयोग आपके द्वारा देखे गए अपवाद को देगा। सीएलआर (डिफ़ॉल्ट रूप से) केवल किसी भी अंतर्निहित COM ऑब्जेक्ट के लिए एक एकल आरसीडब्ल्यू बनाता है, इसलिए इसका मतलब है कि यदि आप जिस COM API का उपयोग कर रहे हैं, वह दो बार एक ही ऑब्जेक्ट लौटाता है, तो यह सिर्फ एक ही आरसीडब्ल्यू होगा। कॉलिंग FinalReleaseComObjectwould का मतलब है कि अचानक सभी उस आरसीडब्ल्यू के उपयोग टोस्ट हैं।

आपके पास गारंटी देने का एकमात्र तरीका एक अद्वितीय मार्शल है। GetUniqueObjectForI अज्ञात, जो किसी भी आरसीडब्ल्यू साझाकरण को रोकता है। लेकिन जैसा कि मैंने पहले कहा था, अधिकांश COM एपीआई में यह पहली जगह में करने में असमर्थ नहीं है, इसलिए बस इसे न करें।

पॉल हैरिंगटन ने [अंतिम] रिलीजकॉम ऑब्जेक्ट और इसकी बुराइयों के बारे में एक अच्छा blog post लिखा। यह एक खतरनाक हथियार है कि जब तक आवश्यक न केवल आपको चोट पहुंचाए। चूंकि आप इस सवाल से पूछ रहे हैं, मुझे संदेह होगा कि आपको वास्तव में इसे कॉल करने की ज़रूरत नहीं है। :-)

+0

धन्यवाद आपके इनपुट के लिए जेसन। क्या यह स्पष्टीकरण रिलीजकॉम ऑब्जेक्ट विधि के लिए भी सच है? क्योंकि, जब मैं इसे FinalReleaseCOMObject की बजाय उपयोग करता हूं, तो भी मुझे वही व्यवहार दिखाई देता है ... यानी 3.5 पर काम करता है लेकिन नहीं 4.0 पर भी। यह सोच रहा था कि .NET फ्रेमवर्क संस्करण को इस व्यवहार के साथ क्या करना है? क्या ऐसा इसलिए है क्योंकि जिस तरह जीसी काम अब 4.0 में बदल गया है? – user74042

+1

तो आरसीडब्ल्यू के पास एक रिफाउंट है जो मार्शल को कॉल करते समय घट जाती है। रिलीज कॉम ऑब्जेक्ट। FinalReleaseComObject बस कॉल करता है जब तक कि refcount शून्य हिट नहीं हो जाता है। –

+1

जहां तक ​​सीएलआर में बदल गया, जिसके कारण यह ...डीबगर के बिना कहना मुश्किल है। –