2013-06-06 16 views
5

मैं एक C++/CLI कार्यान्वित finalizer और नाशक के साथ नाम "CTransferManaged" वर्ग है इस्तेमाल किया नहीं कहा:सी #/CLI: नाशक अगर निपटान() में यह

CTransferManaged::~CTransferManaged() 
{ 
    this->!CTransferManaged(); 
} 
CTransferManaged::!CTransferManaged() 
{ 
    //Clean up resources... 
} 

इस वर्ग के एक सी # वर्ग के साथ लिपटे है नामित "CTransfer" एक ऑब्जेक्ट m_transfer प्रकार का प्रकार CTransferManaged है।

इस वर्ग के नाशक केवल m_transfer मैं देख सकता हूँ कि नाशक कहा जाता है (ब्रेकप्वाइंट मारा जाता है) वस्तु के संदर्भ को साफ करता है, तो:

~CTransfer() 
{ 
    m_transfer = null; //breakpoint on this line 
} 

अगर मैं m_transfer का निपटान() फ़ंक्शन को कॉल करें किसी और चीज को बदले बिना ऑब्जेक्ट, विनाशक अब और नहीं कहा जाता है (ब्रेकपॉइंट और अधिक हिट नहीं)। कोई अनुमान क्यों?

~CTransfer() 
{ 
    m_transfer.Dispose(); //breakpoint on this line 
    m_transfer = null; 
} 

मैं निपटान() कॉल करने के लिए मैन्युअल रूप से के बाद से मुझे पता चला कि C++/CLI वस्तु (m_transfer) के संसाधनों का ठीक से साफ नहीं कर रहे हैं अगर मैं कॉल मैन्युअल फेंक नहीं है चाहते हैं। फिलहाल मुझे नहीं पता कि क्यों।

सीट्रांसफर (सी # कक्षा) के विनाशक को जितनी जल्दी कहा जाता है उतना ही नहीं कहा जाता है जितना इसे CTransferManaged :: Dispose() (C++/CLI) कहते हैं?

+0

आपका सीट्रांसफर वर्ग * आईडीआईस्पोज़ेबल को लागू करना चाहिए ताकि यह m_transfer सदस्य को सही ढंग से निपटान कर सके। ऐसा लगता है कि आपने ऐसा किया था। ** ** ** CTransfer के लिए अंतिमकरण लागू नहीं करें। किसी सदस्य को शून्य पर सेट करने से कोई उपयोगी प्रभाव नहीं पड़ता है और इसकी निपटान() विधि को कॉल करना गलत है। –

+0

@ हंसपैसेंट: CTransfer के अंतिमकर्ता के भीतर किसी सदस्य ऑब्जेक्ट (m_transfer) की निपटान() विधि को कॉल करना गलत क्यों है? जैसा कि मैंने उल्लेख किया है, मुझे पता चला है कि m_transfer के संसाधन ठीक से साफ़ नहीं होते हैं जब मैं उस पर निपटान() नहीं कहता ( obruend

उत्तर

0

सी # विनाशक केवल कचरा कलेक्टर द्वारा बुलाया जाता है और आप इसे सीधे कॉल नहीं कर सकते हैं।

निपटान करें कि IDISposalbe इंटरफ़ेस का हिस्सा कौन सा मैन्युअल रूप से कहा जाना चाहिए और यह विनाशक को आग नहीं देगा।

विनाशक पर भरोसा करने के बजाय iDisposabe को लागू करने का प्रयास करें और निपटान विधि को सीधे बुलाएं और अपना कोड वहां रखें।

संसाधन वर्ग एम्बेडेड ऑब्जेक्ट कि निपटारा किया जाना चाहिए है, तो इस पैटर्न के साथ सी # की जरूरत है:

// C# 
public class Resource : IDisposable 
{ 
    private EmbeddedResource embedded; 

    public Resource() 
    { 
     Console.WriteLine("allocating resource"); 
     embedded = new EmbeddedResource(); 
    } 

    ~Resource() 
    { 
     Dispose(false); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     Console.WriteLine("release resource"); 
     if (disposing) 
     { 
     embedded.Dispose(); 
     } 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 
} 
+0

ध्यान दें कि मैं मैन्युअल रूप से निपटाना नहीं चाहता() सी # ऑब्जेक्ट (कक्षा CTransfer)। मैं बस अपने सदस्य m_transfer (क्लास CTransferManaged) के मैन्युअल निपटान का उपयोग करना चाहता हूं क्योंकि इसके संसाधन ठीक से अन्यथा साफ नहीं किए जाते हैं। – obruend

0

निपटान और अंतिम रूप दिया जा ऐसी है कि जब आप निपटान फोन, finalizer दबा दिया जाना चाहिए के लिए विशिष्ट पैटर्न । निपटान का उद्देश्य संसाधनों को जल्द से जल्द निष्पादित करना है, जबकि अंतिमकर्ता संसाधनों को साफ़ करने के लिए है जब कचरा कलेक्टर कक्षा एकत्र करता है ... दोनों एक ही काम (अप्रबंधित संसाधनों को छोड़ दें) करने के लिए हैं, और इसलिए यदि आप कॉल करते हैं निपटान करें, फाइनलर को कॉल करना अनावश्यक और अनावश्यक होगा, और इससे ऑब्जेक्ट को लंबे समय तक जीने की भी आवश्यकता होगी क्योंकि इससे पहले इसे एकत्रित और नष्ट करने से पहले फाइनलाइज़र कतार पर रखा जाएगा। इससे अत्यधिक एक्सेस किए गए अनुप्रयोगों पर खराब स्मृति प्रबंधन होता है जो कई ऑब्जेक्ट्स बनाते हैं और उनका निपटान करते हैं। इसलिए, सी # में सबसे अधिक निपटान विधियां कॉल करेंगी:

GC.SuppressFinalize(this); 

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

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