c# - IDISposable इंटरफ़ेस का उचित उपयोग



.net garbage-collection (16)

IDisposable is good for unsubscribing from events.

मुझे एमएसडीएन दस्तावेज पढ़ने से पता है कि IDisposable इंटरफेस का "प्राथमिक" उपयोग अप्रबंधित संसाधनों को साफ करना है।

मेरे लिए, "अप्रबंधित" का मतलब डेटाबेस कनेक्शन, सॉकेट, खिड़की हैंडल इत्यादि जैसी चीजें हैं, लेकिन, मैंने कोड देखा है जहां Dispose() विधि को प्रबंधित संसाधनों के लिए लागू किया गया है, जो मुझे अनावश्यक लगता है, क्योंकि कचरा कलेक्टर को चाहिए आपके लिए इसका ख्याल रखना

उदाहरण के लिए:

public class MyCollection : IDisposable
{
    private List<String> _theList = new List<String>();
    private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();

    // Die, clear it up! (free unmanaged resources)
    public void Dispose()
    {
        _theList.clear();
        _theDict.clear();
        _theList = null;
        _theDict = null;
    }

मेरा सवाल यह है कि क्या यह कचरा कलेक्टर मुफ्त मेमोरी को MyCollection द्वारा सामान्य रूप से इस्तेमाल किया जाता है?

संपादित करें : अब तक लोगों ने डेटाबेस कनेक्शन और बिटमैप्स जैसे अप्रबंधित संसाधनों को साफ करने के लिए IDISposable का उपयोग करने के कुछ अच्छे उदाहरण पोस्ट किए हैं। लेकिन मान लीजिए कि उपर्युक्त कोड में सूची में लाखों तार हैं, और आप अब कचरा कलेक्टर की प्रतीक्षा करने के बजाय उस स्मृति को मुक्त करना चाहते हैं । क्या उपर्युक्त कोड पूरा करेगा?


There are things that the Dispose() operation does in the example code that might have an effect that would not occur due to a normal GC of the MyCollection object.

If the objects referenced by _theList or _theDict are referred to by other objects, then that List<> or Dictionary<> object will not be subject to collection but will suddenly have no contents. If there were no Dispose() operation as in the example, those collections would still contain their contents.

Of course, if this were the situation I would call it a broken design - I'm just pointing out (pedantically, I suppose) that the Dispose() operation might not be completely redundant, depending on whether there are other uses of the List<> or Dictionary<> that are not shown in the fragment.


The most justifiable use case for disposal of managed resources, is preparation for the GC to reclaim resources that would otherwise never be collected.

A prime example is circular references.

Whilst it's best practice to use patterns that avoid circular references, if you do end up with (for example) a 'child' object that has a reference back to its 'parent', this can stop GC collection of the parent if you just abandon the reference and rely on GC - plus if you have implemented a finalizer, it'll never be called.

The only way round this is to manually break the circular references by setting the Parent references to null on the children.

Implementing IDisposable on parent and children is the best way to do this. When Dispose is called on the Parent, call Dispose on all Children, and in the child Dispose method, set the Parent references to null.


In the example you posted, it still doesn't "free the memory now". All memory is garbage collected, but it may allow the memory to be collected in an earlier generation . You'd have to run some tests to be sure.

The Framework Design Guidelines are guidelines, and not rules. They tell you what the interface is primarily for, when to use it, how to use it, and when not to use it.

I once read code that was a simple RollBack() on failure utilizing IDisposable. The MiniTx class below would check a flag on Dispose() and if the Commit call never happened it would then call Rollback on itself. It added a layer of indirection making the calling code a lot easier to understand and maintain. The result looked something like:

using( MiniTx tx = new MiniTx() )
{
    // code that might not work.

    tx.Commit();
} 

I've also seen timing / logging code do the same thing. In this case the Dispose() method stopped the timer and logged that the block had exited.

using( LogTimer log = new LogTimer("MyCategory", "Some message") )
{
    // code to time...
}

So here are a couple of concrete examples that don't do any unmanaged resource cleanup, but do successfully used IDisposable to create cleaner code.


One problem with most discussions of "unmanaged resources" is that they don't really define the term, but seem to imply that it has something to do with unmanaged code. While it is true that many types of unmanaged resources do interface with unmanaged code, thinking of unmanaged resources in such terms isn't helpful.

Instead, one should recognize what all managed resources have in common: they all entail an object asking some outside 'thing' to do something on its behalf, to the detriment of some other 'things', and the other entity agreeing to do so until further notice. If the object were to be abandoned and vanish without a trace, nothing would ever tell that outside 'thing' that it no longer needed to alter its behavior on behalf of the object that no longer existed; consequently, the 'thing's usefulness would be permanently diminished.

An unmanaged resource, then, represents an agreement by some outside 'thing' to alter its behavior on behalf of an object, which would useless impair the usefulness of that outside 'thing' if the object were abandoned and ceased to exist. A managed resource is an object which is the beneficiary of such an agreement, but which has signed up to receive notification if it is abandoned, and which will use such notification to put its affairs in order before it is destroyed.


Apart from its primary use as a way to control the lifetime of system resources (completely covered by the awesome answer of Ian , kudos!), the IDisposable/using combo can also be used to scope the state change of (critical) global resources : the console , the threads , the process , any global object like an application instance .

I've written an article about this pattern: http://pragmateek.com/c-scope-your-global-state-changes-with-idisposable-and-the-using-statement/

It illustrates how you can protect some often used global state in a reusable and readable manner: console colors , current thread culture , Excel application object properties ...


If anything, I'd expect the code to be less efficient than when leaving it out.

Calling the Clear() methods are unnecessary, and the GC probably wouldn't do that if the Dispose didn't do it...


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

निम्नलिखित उदाहरण कुछ कोड और टिप्पणियों के साथ आईडीस्पोजेबल पैटर्न के लिए एक अच्छा उदाहरण दिखाता है।

public class DisposeExample
{
    // A base class that implements IDisposable. 
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources. 
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource. 
        private IntPtr handle;
        // Other managed resource this class uses. 
        private Component component = new Component();
        // Track whether Dispose has been called. 
        private bool disposed = false;

        // The class constructor. 
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable. 
        // Do not make this method virtual. 
        // A derived class should not be able to override this method. 
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios. 
        // If disposing equals true, the method has been called directly 
        // or indirectly by a user's code. Managed and unmanaged resources 
        // can be disposed. 
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed. 
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called. 
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources. 
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here. 
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary 
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code. 
        // This destructor will run only if the Dispose method 
        // does not get called. 
        // It gives your base class the opportunity to finalize. 
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here. 
            // Calling Dispose(false) is optimal in terms of 
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create 
        // and use the MyResource object.
    }
}

Yep, that code is completely redundant and unnecessary and it doesn't make the garbage collector do anything it wouldn't otherwise do (once an instance of MyCollection goes out of scope, that is.) Especially the .Clear() calls.

Answer to your edit: Sort of. If I do this:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has no Dispose() method
    instance.FillItWithAMillionStrings();
}

// 1 million strings are in memory, but marked for reclamation by the GC

It's functionally identical to this for purposes of memory management:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has your Dispose()
    instance.FillItWithAMillionStrings();
    instance.Dispose();
}

// 1 million strings are in memory, but marked for reclamation by the GC

If you really really really need to free the memory this very instant, call GC.Collect() . There's no reason to do this here, though. The memory will be freed when it's needed.


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

निपटान पैटर्न को कार्यान्वित करने के तरीके के बारे में अधिक जानकारी के लिए आप इस article को देख सकते हैं, लेकिन यह मूल रूप से इस तरह दिखता है:

public class SimpleCleanup : IDisposable
{
    // some fields that require cleanup
    private SafeHandle handle;
    private bool disposed = false; // to detect redundant calls

    public SimpleCleanup()
    {
        this.handle = /*...*/;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                if (handle != null)
                {
                    handle.Dispose();
                }
            }

            // Dispose unmanaged managed resources.

            disposed = true;
        }
    }

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

यहां सबसे महत्वपूर्ण तरीका यह है कि निपटान (बूल) है, जो वास्तव में दो अलग-अलग परिस्थितियों में चलता है:

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

जीसी को क्लीनअप करने का ख्याल रखने की समस्या यह है कि जीसी एक संग्रह चक्र चलाएगा जब आप जीसी.कोलेक्ट () को कॉल कर सकते हैं, लेकिन आपको वास्तव में नहीं करना चाहिए) तो संसाधनों का कोई वास्तविक नियंत्रण नहीं है, लेकिन संसाधन वास्तव में नहीं रह सकते हैं जरूरत से अधिक के आसपास। याद रखें, निपटान () को वास्तव में संग्रह चक्र का कारण नहीं बनता है या किसी भी तरह से जीसी वस्तु को एकत्र / मुक्त करने का कारण बनता है; यह केवल संसाधनों को अधिक निर्धारित रूप से साफ करने के साधन प्रदान करता है और जीसी को बताता है कि यह सफाई पहले से ही कर दी गई है।

IDISposable और निपटान पैटर्न का पूरा बिंदु स्मृति को तुरंत मुक्त करने के बारे में नहीं है। निपटने का एकमात्र समय वास्तव में स्मृति को तुरंत मुक्त करने का मौका भी होगा जब यह निपटान == झूठी परिदृश्य को संभालने और अप्रबंधित संसाधनों में हेरफेर कर रहा है। प्रबंधित कोड के लिए, जीसी वास्तव में पुनः दावा नहीं किया जाएगा जब तक कि जीसी एक संग्रह चक्र चलाता है, जिसका आपके पास वास्तव में कोई नियंत्रण नहीं है (जीसी.कोलेक्ट () को कॉल करने के अलावा, जिसे मैंने पहले ही उल्लेख किया है, एक अच्छा विचार नहीं है)।

आपका परिदृश्य वास्तव में मान्य नहीं है क्योंकि .NET में तार किसी भी असंगत संसाधनों का उपयोग नहीं करते हैं और IDISposable लागू नहीं करते हैं, उन्हें "साफ करने" के लिए मजबूर करने का कोई तरीका नहीं है।


First of definition. For me unmanaged resource means some class, which implements IDisposable interface or something created with usage of calls to dll. GC doesn't know how to deal with such objects. If class has for example only value types, then I don't consider this class as class with unmanaged resources. For my code I follow next practices:

  1. If created by me class uses some unmanaged resources then it means that I should also implement IDisposable interface in order to clean memory.
  2. Clean objects as soon as I finished usage of it.
  3. In my dispose method I iterate over all IDisposable members of class and call Dispose.
  4. In my Dispose method call GC.SuppressFinalize(this) in order to notify garbage collector that my object was already cleaned up. I do it because calling of GC is expensive operation.
  5. As additional precaution I try to make possible calling of Dispose() multiple times.
  6. Sometime I add private member _disposed and check in method calls did object was cleaned up. And if it was cleaned up then generate ObjectDisposedException
    Following template demonstrates what I described in words as sample of code:

public class SomeClass : IDisposable
    {
        /// <summary>
        /// As usually I don't care was object disposed or not
        /// </summary>
        public void SomeMethod()
        {
            if (_disposed)
                throw new ObjectDisposedException("SomeClass instance been disposed");
        }

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

        private bool _disposed;

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;
            if (disposing)//we are in the first call
            {
            }
            _disposed = true;
        }
    }


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

प्रबंधित / अप्रबंधित और अन्य उत्तरों में चर्चा के बारे में सामान्य प्रश्न के लिए, मुझे लगता है कि इस प्रश्न का कोई जवाब किसी अप्रबंधित संसाधन की परिभाषा से शुरू करना है।

यह क्या उबालता है कि एक ऐसा कार्य है जिसे आप सिस्टम को राज्य में रखने के लिए बुला सकते हैं, और एक और कार्य है जिसे आप उस राज्य से वापस लाने के लिए बुला सकते हैं। अब, सामान्य उदाहरण में, पहला एक ऐसा फ़ंक्शन हो सकता है जो फ़ाइल हैंडल देता है, और दूसरा एक CloseHandle को कॉल कर CloseHandle

लेकिन - और यह कुंजी है - वे किसी भी मिलान की जोड़ी हो सकती हैं। एक राज्य बनाता है, दूसरा इसे आँसू देता है। अगर राज्य बनाया गया है लेकिन अभी तक फाड़ा नहीं गया है, तो संसाधन का एक उदाहरण मौजूद है। आपको सही समय पर टियरडाउन होने की व्यवस्था करनी है - संसाधन सीएलआर द्वारा प्रबंधित नहीं किया जाता है। केवल स्वचालित रूप से प्रबंधित संसाधन प्रकार स्मृति है। दो प्रकार हैं: जीसी, और ढेर। मूल्य प्रकारों को ढेर द्वारा प्रबंधित किया जाता है (या संदर्भ प्रकारों के अंदर एक सवारी को घुमाकर), और संदर्भ प्रकार जीसी द्वारा प्रबंधित किए जाते हैं।

ये कार्य राज्य परिवर्तनों का कारण बन सकते हैं जिन्हें स्वतंत्र रूप से अंतःस्थापित किया जा सकता है, या पूरी तरह से घोंसले की आवश्यकता हो सकती है। राज्य परिवर्तन थ्रेडसेफ हो सकता है, या वे शायद नहीं।

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

अपने अप्रबंधित संसाधनों को साफ करने के लिए कचरा कलेक्टर के साथ एक सवारी करना संभव है। लेकिन केवल अगर राज्य परिवर्तन कार्य थ्रेडसेफ हैं और दो राज्यों में जीवनकाल हो सकता है जो कि किसी भी तरह से ओवरलैप हो। तो संसाधन के न्याय के उदाहरण को अंतिम रूप देने वाला नहीं होना चाहिए! यह सिर्फ किसी की मदद नहीं करेगा।

उन प्रकार के संसाधनों के लिए, आप केवल अंतिम रूप के बिना IDisposable लागू कर सकते हैं। फाइनलाइज़र बिल्कुल वैकल्पिक है - यह होना चाहिए। यह कई किताबों में भी उभरा है या यहां तक ​​कि उल्लेख नहीं किया गया है।

इसके बाद आपको Dispose का कोई मौका देने के लिए using कथन का using करना होगा। यह अनिवार्य रूप से स्टैक के साथ एक सवारी को घुमाने जैसा है (इसलिए फाइनलजर जीसी के लिए है, स्टैक के लिए using है)।

लापता हिस्सा यह है कि आपको मैन्युअल रूप से निपटाना होगा और इसे अपने फ़ील्ड और अपनी बेस क्लास पर कॉल करना होगा। सी ++ / सीएलआई प्रोग्रामर को ऐसा करने की ज़रूरत नहीं है। कंपाइलर ज्यादातर मामलों में उनके लिए लिखता है।

एक विकल्प है, जिसे मैं उन राज्यों के लिए पसंद करता हूं जो पूरी तरह से घोंसला करते हैं और थ्रेडसेफ नहीं होते हैं (किसी और चीज के अलावा, IDISposable स्पेयर से बचने से आपको किसी ऐसे व्यक्ति के साथ तर्क करने की समस्या होती है जो आईडीआईएसपीबल लागू करने वाले प्रत्येक वर्ग को अंतिम रूप देने का विरोध नहीं कर सकता) ।

कक्षा लिखने के बजाय, आप एक समारोह लिखते हैं। फ़ंक्शन वापस कॉल करने के लिए एक प्रतिनिधि को स्वीकार करता है:

public static void Indented(this Log log, Action action)
{
    log.Indent();
    try
    {
        action();
    }
    finally
    {
        log.Outdent();
    }
}

और फिर एक साधारण उदाहरण होगा:

Log.Write("Message at the top");
Log.Indented(() =>
{
    Log.Write("And this is indented");

    Log.Indented(() =>
    {
        Log.Write("This is even more indented");
    });
});
Log.Write("Back at the outermost level again");

लैम्ब्डा पास होने के कारण कोड ब्लॉक के रूप में कार्य करता है, इसलिए ऐसा लगता है कि आप अपनी खुद की नियंत्रण संरचना का using उसी उद्देश्य को पूरा करने के लिए using , सिवाय इसके कि अब आपको कॉलर का दुरुपयोग करने का कोई खतरा नहीं है। संसाधन को साफ करने में कोई रास्ता नहीं है।

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


I won't repeat the usual stuff about Using or freeing un-managed resources, that has all been covered. But I would like to point out what seems a common misconception.
Given the following code

Public Class LargeStuff
  Implements IDisposable
  Private _Large as string()

  'Some strange code that means _Large now contains several million long strings.

  Public Sub Dispose() Implements IDisposable.Dispose
    _Large=Nothing
  End Sub

I realise that the Disposable implementation does not follow current guidelines, but hopefully you all get the idea.
Now, when Dispose is called, how much memory gets freed?

Answer: None.
Calling Dispose can release unmanaged resources, it CANNOT reclaim managed memory, only the GC can do that. Thats not to say that the above isn't a good idea, following the above pattern is still a good idea in fact. Once Dispose has been run, there is nothing stopping the GC re-claiming the memory that was being used by _Large, even though the instance of LargeStuff may still be in scope. The strings in _Large may also be in gen 0 but the instance of LargeStuff might be gen 2, so again, memory would be re-claimed sooner.
There is no point in adding a finaliser to call the Dispose method shown above though. That will just DELAY the re-claiming of memory to allow the finaliser to run.


यदि MyCollection कचरा होने जा रहा है, तो आपको इसे निपटाने की आवश्यकता नहीं है। ऐसा करने से सीपीयू को जरूरी से ज़्यादा मंथन मिलेगा, और कचरा कलेक्टर पहले ही कुछ पूर्व-गणना वाले विश्लेषण को अमान्य कर सकता है।

मैं ऐसी चीजों को IDisposable लिए IDisposable का उपयोग करता हूं जैसे कि अप्रबंधित संसाधनों के साथ थ्रेड का सही ढंग से निपटान किया जाता है।

स्कॉट की टिप्पणी के जवाब में संपादित करें :

जीसी प्रदर्शन मीट्रिक प्रभावित होने का एकमात्र समय तब होता है जब एक [एसआईसी] जीसी.कोलेक्ट () को कॉल किया जाता है "

संकल्पनात्मक रूप से, जीसी ऑब्जेक्ट संदर्भ ग्राफ का एक दृश्य रखता है, और धागे के ढेर फ्रेम से इसके सभी संदर्भों को बनाए रखता है। यह ढेर काफी बड़ा हो सकता है और स्मृति के कई पेजों का विस्तार कर सकता है। एक अनुकूलन के रूप में, जीसी उन पृष्ठों के विश्लेषण को कैश करता है जो पृष्ठ को अनावश्यक रूप से सहेजने से बचने के लिए अक्सर बदलने की संभावना नहीं होती हैं। जब पृष्ठ में डेटा बदलता है तो जीसी कर्नेल से अधिसूचना प्राप्त करता है, इसलिए यह जानता है कि पृष्ठ गंदा है और इसके लिए एक rescan की आवश्यकता है। यदि संग्रह Gen0 में है तो यह संभावना है कि पृष्ठ में अन्य चीजें भी बदल रही हैं, लेकिन यह Gen1 और Gen2 में कम संभावना है। अनजाने में, ये हुक उस मंच के लिए मैक ओएस एक्स में उपलब्ध नहीं थे, जिन्होंने उस प्लेटफॉर्म पर सिल्वरलाइट प्लग-इन काम करने के लिए जीसी को मैक को पोर्ट किया था।

संसाधनों के अनावश्यक निपटान के खिलाफ एक और बिंदु: ऐसी स्थिति की कल्पना करें जहां एक प्रक्रिया उतार रही है। कल्पना कीजिए कि प्रक्रिया कुछ समय से चल रही है। संभावना है कि उस प्रक्रिया के कई मेमोरी पेज डिस्क पर बदल दिए गए हैं। कम से कम वे अब एल 1 या एल 2 कैश में नहीं हैं। ऐसी स्थिति में ऐसे सभी डेटा और कोड पृष्ठों को स्मृति में वापस लाने के लिए अनलोड करने के लिए कोई समस्या नहीं है जो प्रक्रिया को समाप्त होने पर ऑपरेटिंग सिस्टम द्वारा जारी किए जाने वाले 'रिलीज़' संसाधनों को स्मृति में वापस ले जाया जा सकता है। यह प्रबंधित और यहां तक ​​कि कुछ अप्रबंधित संसाधनों पर भी लागू होता है। केवल संसाधन जो गैर-पृष्ठभूमि धागे को जीवित रखते हैं उन्हें निपटान किया जाना चाहिए, अन्यथा प्रक्रिया जीवित रहेगी।

अब, सामान्य निष्पादन के दौरान अस्थायी संसाधनों को ठीक से साफ किया जाना चाहिए (जैसा कि @fezmonkey डेटाबेस कनेक्शन, सॉकेट, विंडो हैंडल को इंगित करता है ) अप्रबंधित स्मृति रिसाव से बचने के लिए। ये ऐसी चीजें हैं जिन्हें निपटान किया जाना है। If you create some class that owns a thread (and by owns I mean that it created it and therefore is responsible for ensuring it stops, at least by my coding style), then that class most likely must implement IDisposable and tear down the thread during Dispose .

The .NET framework uses the IDisposable interface as a signal, even warning, to developers that the this class must be disposed. I can't think of any types in the framework that implement IDisposable (excluding explicit interface implementations) where disposal is optional.


करने के लिए (गलत-) बोली रेमंड चेन: एक समाप्ति नीति के बिना हर कैश एक रिसाव है

इसलिए, एक साफ़ कैश समाप्ति नीति सेट करें, और कैश को सामान्य केस के रूप में निपटाने दें। यह अभी भी आवेदन शटडाउन को नियंत्रित करने के लिए छोड़ देता है।

यदि आपके अप्रबंधित ressources प्रक्रिया के स्वामित्व में हैं, तो आप प्रक्रिया बंद करने पर उन्हें जारी कर सकते हैं।

अगर अप्रबंधित ressources प्रक्रिया के स्वामित्व में नहीं हैं, तो आप बंद करने का पता लगाने और स्पष्ट रूप से कैश्ड तत्वों को निकालना होगा।

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

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





c# .net garbage-collection idisposable