2009-10-15 13 views
16

मैं एक प्रबंधित वस्तु है कि एक COM सर्वर कॉल कुछ स्मृति को आबंटित करने की है। प्रबंधित ऑब्जेक्ट को मेमोरी लीक से बचने के लिए प्रबंधित ऑब्जेक्ट से पहले उस स्मृति को मुक्त करने के लिए COM ऑब्जेक्ट को फिर से कॉल करना होगा। यह ऑब्जेक्ट IDisposable लागू करता है ताकि यह सुनिश्चित करने में सहायता मिल सके कि सही मेमोरी-रिलीज़िंग COM कॉल किया गया है।क्या अंतिम बार से आरसीडब्ल्यू कॉल करना सुरक्षित है?

यदि Dispose विधि नहीं है, तो मैं ऑब्जेक्ट के फ़ाइनलज़र को स्मृति मुक्त करने के लिए चाहता हूं। मुसीबत को अंतिम रूप देने के नियमों है कि आप क्योंकि आप नहीं जानते कि क्या अन्य वस्तुओं पहले से ही GC'd गया और/या आप से पहले अंतिम रूप दे दिया किसी भी संदर्भ का उपयोग नहीं करना चाहिए, है। यह फ़ील्ड होने के लिए एकमात्र स्पर्श करने योग्य वस्तु स्थिति छोड़ देता है (हैंडल सबसे आम है)।

लेकिन एक COM सर्वर बुला स्मृति है कि मैं एक क्षेत्र में संग्रहीत करने के लिए एक कुकी है, मुक्त करने के लिए एक क्रम प्रतिदेय आवरण (RCW) के माध्यम से जा शामिल है। कि RCW सुरक्षित एक finalizer (यह GC'd को नहीं की गई या अंतिम रूप दे दिया इस बिंदु पर गारंटी है) से कॉल करने के लिए है?

अंतिम रूप दिए जाने के साथ नहीं परिचित आप में से उन लोगों के लिए है, हालांकि finalizer धागा एक प्रबंधित appdomain की पृष्ठभूमि में चलता है अपनी चल रहा है, पर उन मामलों के संदर्भ को छू के लिए सैद्धांतिक रूप से ठीक हो सकता है, अंतिम रूप देने के भी appdomain बंद में होता है, और जबकि किसी भी क्रम में - न केवल संदर्भ संबंध आदेश में। यह आपके सीमा को सीमित करने के लिए सुरक्षित है जो आप मान सकते हैं। किसी प्रबंधित ऑब्जेक्ट का कोई भी संदर्भ "खराब" (संग्रहित स्मृति) हो सकता है भले ही संदर्भ गैर-शून्य हो।

अद्यतन: मैं बस यह कोशिश की और यह मिल गया:

प्रकार 'System.Runtime.InteropServices.InvalidComObjectException' की एक बिना क्रिया का अपवाद myassembly.dll

अतिरिक्त जानकारी में हुई: COM वस्तु जिसे इसके अंतर्निहित आरसीडब्ल्यू से अलग किया गया है, का उपयोग नहीं किया जा सकता है।

+0

COM सर्वर पर एक विधि (क्यों कोई भी आरसीडब्ल्यू पर निपटान क्यों करेगा? अगर यह भी संभव है तो मुझे आश्चर्य होगा)। –

उत्तर

16

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

class MyManagedObject : IDisposable 
{ 
    private ISomeObject comServer; 
    private GCHandle rcwHandle; 
    private IServiceProvider serviceProvider; 
    private uint cookie; 

    public MyManagedObject(IServiceProvider serviceProvider) 
    { 
     this.serviceProvider = serviceProvider; 
     this.comServer = this. serviceProvider.GetService(/*some service*/) as ISomeObject; 
     this.rcwHandle = GCHandle.Alloc(this.comServer, GCHandleType.Normal); 
     this.cookie = comServer.GetCookie(); 
    } 

    ~MyManagedObject() 
    { 
     this.Dispose(false); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // dispose owned managed objects here. 
     } 

     if (this.rcwHandle.IsAllocated) 
     { 
      // calling this RCW is safe because we have a GC handle to it. 
      this.comServer.ReleaseCookie(this.cookie); 

      // Now release the GC handle on the RCW so it can be freed as well 
      this.rcwHandle.Free(); 
     } 
    } 
} 

यह मेरी विशेष मामले में पता चला है, मेरे ऐप CLR ही आयोजन कर रहा है। इसलिए, यह mscoree कॉल कर रहा है! CoEEShutdownCOM से पहले finalizer धागा जो InvalidComObjectException त्रुटि मैं देख रहा था में RCW और परिणाम को मारता है चलाने के लिए हो जाता है,।

लेकिन सामान्य मामलों में जहां CLR खुद की मेजबानी नहीं है, मुझे बताया गया हूँ इस काम करना चाहिए।

+0

हैलो एंड्रयू, और इस पोस्ट के लिए धन्यवाद।मैं 'IAudioSessionControl2' COM इंटरफ़ेस को लपेटने वाली कक्षा में आपके सुझाए गए समाधान को लागू करने का प्रयास कर रहा हूं। कक्षा 'आईडीस्पोजेबल' इंटरफ़ेस लागू करती है, 'IAudioSessionControl2' इंटरफ़ेस-इवेंट' पर 'मार्शल। रिलीज कॉमऑब्जेक्ट' को कॉल करती है, जिसके परिणामस्वरूप आप जिस त्रुटि का जिक्र कर रहे हैं-उस पर आपकी पोस्ट में। आपके सुझाव को लागू करने के लिए, मैंने 'ऑब्जेक्ट' के साथ 'ISomeObject' (जिसे मैं परिचित नहीं हूं) को बदल दिया, लेकिन कन्स्ट्रक्टर के 'सेवा प्रदाता' तर्क का उपयोग कैसे करें, और कॉल पर कौन सी सेवा दी जानी चाहिए 'GetService' करने के लिए? बहुत आभारी। – Bliss

7

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

+0

मेरे जवाब को हटा दिया क्योंकि यह मेरे मामले में दिखाई देता है मुझे भाग्यशाली डब्ल्यू/फाइनलाइज़र थ्रेड मिला। – user7116

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

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