2010-05-14 16 views
14

List<WeakReference> का उपयोग कर काम नहीं करेगा जैसा मैं चाहता हूं। मैं चाहता हूं कि वीक रेफरेंस स्वचालित रूप से सूची से हटा दिया गया हो, जब भी वे ऑब्जेक्ट संदर्भित करते हैं तो कचरा एकत्र होता है।क्या सीएलआर में कमजोर या कमजोर चयन (जैसे वीक रेफरेंस) करने का कोई तरीका है?

ConditionalWeakTable<TKey,TValue> मुझे संतुष्ट नहीं करता है, क्योंकि यद्यपि इसकी चाबियाँ और मूल्यों को कमजोर संदर्भित और एकत्रित किया जा सकता है, आप उन्हें गणना नहीं कर सकते!

+0

दो जवाब को देखने के लिए अब तक दोनों कुछ नहीं-पूरी तरह से स्वचालित पर्ज कदम है दिलचस्प। मुझे इसके बारे में सोचने में कुछ समय बिताना होगा, लेकिन वास्तव में यह पूरी तरह से स्वचालित नहीं हो सकता है, भले ही यह पूरी तरह से स्वचालित हो। –

+1

पर्जिंग गणना के दौरान सबसे स्वाभाविक रूप से किया जाता है। एकमात्र अन्य विकल्प एक आवधिक शुद्धीकरण होना है, इस स्थिति में समाधान "कमजोर सूची" की तुलना में "कैश" से अधिक हो जाता है। कैशिंग के लिए 'वीक रेफरेंस' का उपयोग नहीं किया जाना चाहिए; इसके लिए बेहतर समाधान हैं (उदा।, [System.Runtime.Caching] (http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx))। –

+0

System.Runtime.Caching के बारे में दिलचस्प सुझाव के लिए धन्यवाद। लेकिन मेरे पास इस प्रश्न के लिए एक विशेष अनुप्रयोग था, और मैं कुछ बाधाओं को देख सकता हूं - 1) मुझे वस्तुओं को पाने के लिए स्ट्रिंग कुंजियों का उपयोग करने की आवश्यकता नहीं है या नहीं, मैं सिर्फ मांग पर उन्हें फिर से स्थापित करने में सक्षम होना चाहता हूं।2) यदि संभवतः कचरा होने के कारण वस्तुओं को कैश छोड़ दिया जाता है, तो मैं शायद अधिक खुश रहूंगा, न कि अन्य विविध कारणों (जैसे कैश बहुत अधिक मेमोरी का उपयोग करके)। –

उत्तर

7

मैं मानता हूँ कि एक WeakList<T> को लागू करने के लिए संभव है, लेकिन मुझे नहीं लगता कि यह वास्तव में आसान है। मेरा कार्यान्वयन here का उपयोग करने के लिए आपका स्वागत है। WeakCollection<T> वर्ग WeakReference<T> पर निर्भर करता है, जो बदले में SafeGCHandle पर निर्भर करता है।

+0

यह एक कोडप्लेक्स परियोजना है ?! बहुत बढ़िया। धन्यवाद। :-) –

+0

@ स्टीफन-क्लीरी - यह आपके सबसे हालिया स्रोत में प्रतीत नहीं होता है, इसलिए मैं इस बारे में उत्सुक हूं कि आप नवीनतम सीएलआर के साथ इस समस्या का सामना कैसे कर रहे हैं। –

+2

@ माइक-ईईई: इफेमरन के लिए, मैं [कनेक्टेड प्रॉपर्टीज] (http://connectedproperties.codeplex.com/) का उपयोग करता हूं। वे गणना का समर्थन नहीं करते हैं, लेकिन मुझे उस क्षमता की कभी आवश्यकता नहीं है। –

6

आप आसानी से WeakList<T> कक्षा लागू कर सकते हैं, जो List<WeakReference> को लपेट देगा।

कचरा इकट्ठा होने पर वस्तुओं को स्वचालित रूप से निकालने का कोई तरीका नहीं है, क्योंकि ऐसा होने पर यह पता लगाना संभव नहीं है। हालांकि, WeakReference.IsAlive संपत्ति की जांच करके, जब आप उन्हें सामना करते हैं तो आप "मृत" (कचरा एकत्रित) वस्तुओं को निकाल सकते हैं। हालांकि, मैं इस दृष्टिकोण की अनुशंसा नहीं करता, क्योंकि इससे ग्राहक के दृष्टिकोण से भ्रमित व्यवहार हो सकता है। इसके बजाय, मैं मृत प्रविष्टियों को हटाने के लिए Purge विधि को लागू करने की अनुशंसा करता हूं, जिसे आप स्पष्ट रूप से कॉल करेंगे।

WeakReference<T> (WeakReference चारों ओर सिर्फ एक दृढ़ता से टाइप किया आवरण)

[Serializable] 
public class WeakReference<T> : WeakReference 
{ 
    public WeakReference(T target) 
     : base(target) 
    { 
    } 

    public WeakReference(T target, bool trackResurrection) 
     : base(target, trackResurrection) 
    { 
    } 

    public WeakReference(SerializationInfo info, StreamingContext context) 
     : base(info, context) 
    { 
    } 

    public new T Target 
    { 
     get 
     { 
      return (T)base.Target; 
     } 
    } 
} 

:

public class WeakList<T> : IList<T> 
{ 
    private List<WeakReference<T>> _innerList = new List<WeakReference<T>>(); 

    #region IList<T> Members 

    public int IndexOf(T item) 
    { 
     return _innerList.Select(wr => wr.Target).IndexOf(item); 
    } 

    public void Insert(int index, T item) 
    { 
     _innerList.Insert(index, new WeakReference<T>(item)); 
    } 

    public void RemoveAt(int index) 
    { 
     _innerList.RemoveAt(index); 
    } 

    public T this[int index] 
    { 
     get 
     { 
      return _innerList[index].Target; 
     } 
     set 
     { 
      _innerList[index] = new WeakReference<T>(value); 
     } 
    } 

    #endregion 

    #region ICollection<T> Members 

    public void Add(T item) 
    { 
     _innerList.Add(new WeakReference<T>(item)); 
    } 

    public void Clear() 
    { 
     _innerList.Clear(); 
    } 

    public bool Contains(T item) 
    { 
     return _innerList.Any(wr => object.Equals(wr.Target, item)); 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     _innerList.Select(wr => wr.Target).CopyTo(array, arrayIndex); 
    } 

    public int Count 
    { 
     get { return _innerList.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return false; } 
    } 

    public bool Remove(T item) 
    { 
     int index = IndexOf(item); 
     if (index > -1) 
     { 
      RemoveAt(index); 
      return true; 
     } 
     return false; 
    } 

    #endregion 

    #region IEnumerable<T> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     return _innerList.Select(x => x.Target).GetEnumerator(); 
    } 

    #endregion 

    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 

    #endregion 

    public void Purge() 
    { 
     _innerList.RemoveAll(wr => !wr.IsAlive); 
    } 
} 

इस वर्ग के निम्नलिखित वर्गों और विस्तार तरीकों का उपयोग करता:

यहां नमूने के कार्यान्वयन है IndexOf,

public static int IndexOf<T>(this IEnumerable<T> source, T item) 
    { 
     var entry = source.Select((x, i) => new { Value = x, Index = i }) 
        .Where(x => object.Equals(x.Value, item)) 
        .FirstOrDefault(); 
     return entry != null ? entry.Index : -1; 
    } 

CopyTo (IList<T>.IndexOf के रूप में ही है, लेकिन एक IEnumerable<T> पर काम करता है) (IList<T>.CopyTo के रूप में ही है, लेकिन एक IEnumerable<T> पर काम करता है)

public static void CopyTo<T>(this IEnumerable<T> source, T[] array, int startIndex) 
    { 
     int lowerBound = array.GetLowerBound(0); 
     int upperBound = array.GetUpperBound(0); 
     if (startIndex < lowerBound) 
      throw new ArgumentOutOfRangeException("startIndex", "The start index must be greater than or equal to the array lower bound"); 
     if (startIndex > upperBound) 
      throw new ArgumentOutOfRangeException("startIndex", "The start index must be less than or equal to the array upper bound"); 

     int i = 0; 
     foreach (var item in source) 
     { 
      if (startIndex + i > upperBound) 
       throw new ArgumentException("The array capacity is insufficient to copy all items from the source sequence"); 
      array[startIndex + i] = item; 
      i++; 
     } 
    } 
+2

यह एक सूची संरचना तैयार करने के लिए .NET 4.0 में संभव होगा जो स्वचालित रूप से अन्य ऑब्जेक्ट्स को सूची में ऑब्जेक्ट संलग्न करने के लिए 'कंडिशनवेकटेबल' का उपयोग करके जीसी'एड की ऑब्जेक्ट्स को हटा देगा, जिससे अंतिम निकासी निष्कासन कर सकें। ध्यान दें कि यह संख्यात्मक रूप से अनुक्रमित सूची के साथ नहीं किया जाना चाहिए (क्योंकि थ्रेड-सुरक्षित फैशन में हटाने को पूरा करने का कोई तरीका नहीं है) लेकिन यह एक लिंक्ड सूची के साथ किया जा सकता है जो चीजों को क्रम में या सृजन के क्रम को उलट देता है। मुझे यकीन नहीं है, हालांकि, किस मामले में सक्रिय रूप से संदर्भों को हटा दिया जाता है क्योंकि वे मर जाते हैं ... – supercat

+0

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

+0

@supercat माना जाता है, लेकिन दुर्भाग्य से फाइनलाइज़र अतिरिक्त मेमोरी + प्रदर्शन लागत के साथ आते हैं और वे पृष्ठभूमि थ्रेड से भाग लेंगे और इस तरह आपको लॉकिंग या थ्रेड सुरक्षित संग्रह का उपयोग करने की आवश्यकता होगी ... (अधिक ओवरहेड्स) –

0

किसी .NET 2.0 या 3.5 में एक ConditionalWeakTable उपयोग करने के लिए की आवश्यकता होगी, के लिए वहाँ यह का बैकपोर्ट यहाँ है: https://github.com/theraot/Theraot/wiki/Features

+0

हाय पैट्रिक। बस अपनी पोस्ट देखी। जहां तक ​​मैं सशर्त वेबकटेबल के दस्तावेज़ों को पढ़ता हूं, वैसे ही संदर्भों को भी नहीं रखता है, यहां तक ​​कि बाहर से ऑब्जेक्ट का एक मजबूत संदर्भ भी है। क्या आपके पास अन्य सूचनाएं हैं? – msedi

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