2009-02-20 15 views
10

मेरे पास एक ऑब्जेक्ट है जो बनाने के लिए महंगा है, जो कुछ अप्रबंधित संसाधनों का उपयोग करता है जिन्हें स्पष्ट रूप से मुक्त किया जाना चाहिए और IDISposable() को कार्यान्वित करना चाहिए। मुझे इन महंगे संसाधनों के उदाहरण के लिए कैश चाहिए ताकि सृजन लागत कम हो, लेकिन मुझे निपटान से निपटने के तरीके को जानने में परेशानी हो रही है।कैश किए गए IDisposable ऑब्जेक्ट्स का प्रबंधन कैसे करें?

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

क्या यह सिर्फ उन्हें दायरे से बाहर जाने और कचरा कलेक्टर द्वारा एकत्रित करने और उस बिंदु पर संसाधनों को मुक्त करने के लिए मान्य है? यह गलत लगता है और उनके विचार के खिलाफ डिस्पोजेबल ...

उत्तर

4

डिस्पोजेबल ऑब्जेक्ट्स को हमेशा एक स्पष्ट मालिक होना चाहिए जो उन्हें निपटाने के लिए ज़िम्मेदार है। हालांकि, यह हमेशा ऐसा ऑब्जेक्ट नहीं है जिसने उन्हें बनाया है। इसके अलावा, स्वामित्व स्थानांतरित किया जा सकता है।

यह समझते हुए, समाधान स्पष्ट हो जाता है। निपटान मत करो, रीसायकल! आपको कैश से संसाधन प्राप्त करने का एकमात्र तरीका नहीं चाहिए, बल्कि इसे वापस करने का एक तरीका भी है। उस बिंदु पर कैश फिर से मालिक है, और भविष्य के उपयोग के लिए संसाधन को बनाए रखने या इसे निपटाने का चयन कर सकता है।

public interface IDisposableItemCache<T> : IDisposable 
     where T:IDisposable 
    { 
     /// <summary> 
     /// Creates a new item, or fetches an available item from the cache. 
     /// </summary> 
     /// <remarks> 
     /// Ownership of the item is transfered from the cache to the client. 
     /// The client is responsible for either disposing it at some point, 
     /// or transferring ownership back to the cache with 
     /// <see cref="Recycle"/>. 
     /// </remarks> 
     T AcquireItem(); 

     /// <summary> 
     /// Transfers ownership of the item back to the cache. 
     /// </summary> 
     void Recycle(T item); 

    } 

संपादित करें: मैं सिर्फ देखा है कि इस विचार को भी, जहां यह एक object pool कहा जाता है वसंत, में मौजूद है। उनके BorrowObject और ReturnObject विधियां मेरे उदाहरण में विधियों से मेल खाते हैं।

+0

मैं मूल रूप से ऐसे समाधान के साथ समाप्त हुआ जो इस और नोबगज़ उत्तर का एक संकर था। धन्यवाद –

2

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

3

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

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

4

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

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

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

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

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

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

0

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

मैं और "कक्षा जाओ" के बजाय क्रम में "कक्षा बनाएँ" पर जोर देना है कि फोन करने वाले निर्माण के लिए जिम्मेदार नहीं है, सुनिश्चित करें कि आपके कारखाने विधि की तरह कुछ नाम है बनाना चाहते इसलिए के लिए नहीं चाहते हैं निपटान।

+0

"निर्माता स्वामी है" एक संभावित डिजाइन दिशानिर्देश है, लेकिन जैसा कि आपका उत्तर पहले ही इंगित करता है: यह हमेशा स्पष्ट नहीं होता कि निर्माता (कारखाना या फैक्ट्री क्लाइंट?) कौन है। स्पष्ट रूप से और स्पष्ट रूप से इसे दस्तावेज करना बेहतर है। जैसा कि मेरा स्वयं का जवाब दिखाता है, आप तब भी स्वामित्व स्थानांतरित कर सकते हैं। –

1

आप इसे कक्षा कारखाने और पहचानने योग्य के साथ हल कर सकते हैं। उदाहरण के लिए:

public class CachedObject : IDisposable { 
    private int mRefCount; 
    private CachedObject(int something) { 
    mRefCount = 1; 
    } 
    public static CachedObject CreateObject(int something) { 
    CachedObject obj = LookupInCache(something); 
    if (obj != null) Interlocked.Increment(ref obj.mRefCount); 
    else obj = new CachedObject(something); 
    return obj; 
    } 
    private static CachedObject LookupInCache(int something) { 
    CachedObject obj = null; 
    // Implement cache lookup here, don't forget to lock 
    //.. 
    return obj; 
    } 
    public void Dispose() { 
    int cnt = Interlocked.Decrement(ref mRefCount); 
    if (cnt == 0) { 
     // Remove from cache 
     // 
    } 
    } 
} 
+0

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

+1

नहीं, अगर यह उत्परिवर्तनीय है तो इसे कैश नहीं किया जाना चाहिए। –

+1

यह कक्षा थ्रेडसेफ नहीं है - आपके इंटरलॉक किए गए inc/decs अगर गार्ड की रक्षा नहीं करते हैं। –

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