2009-07-17 12 views
8

सी #/.NET में, क्या कमजोर संदर्भ द्वारा इंगित वस्तु से पहले अधिसूचना प्राप्त करने का कोई तरीका है? असल में, मैं किसी ऑब्जेक्ट को एकत्रित करने की अनुमति देना चाहता हूं, लेकिन ऑब्जेक्ट को नष्ट करने से पहले कुछ सही कर सकता हूं, विनाशकों को जोड़ने के लिए कोड संशोधित किए बिना (क्योंकि मुझे नहीं पता होगा कि मेरे कोड के साथ किस तरह की ऑब्जेक्ट्स पर मुकदमा चलाया जाएगा)।सी #: वीक रेफरेंस एकत्र करने से पहले अधिसूचना एकत्र की जाती है?

धन्यवाद, रॉबर्ट

उत्तर

5

आप ऐसा नहीं कर सकते हैं। हालांकि आप क्या कर सकते हैं यह देखने के लिए है कि कोई जीसी कब आ रहा है (सीएलआर v3.5Sp1 में नए जीसी एपीआई हैं जो आपको ऐसा करने की अनुमति देते हैं, जीसीएनोटिफिकेशन)

+0

मुझे लगता है कि धारावाहिक डेटा को अद्यतन करने के लिए कोई भी प्राकृतिक स्थान है। जानकारी के लिए धन्यवाद! –

6

नहीं कोई रास्ता नहीं इस कार्यक्षमता को प्राप्त करने के है।

कुछ अटकलों के बाद, मुझे विश्वास नहीं है कि आप जिस तरीके से वर्णन कर रहे हैं उसमें एक सुविधा को लागू करना संभव है।

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

आप देख सकते हैं कि घटना के आसपास दूसरी बार कैसे नहीं उठाया जा सकता क्योंकि यह अनावश्यक वस्तुओं का कारण बनता है।

यह दावा करने का एक दुरुपयोग होगा कि इस घटना को किसी ऑब्जेक्ट को एकत्र करने से ठीक पहले उठाया गया था। सिर्फ इसलिए कि कोई भी हैंडलर वस्तु के लिए एक नया संदर्भ स्थापित करके इसे एकत्रित करने से रोक सकता है। इसके बजाए इसे "ऑब्जेक्टमेबे के बारे में बताया जाना चाहिए"। यह शायद आपको वह व्यवहार नहीं देगा जो आप खोज रहे हैं।

+0

कूल, धन्यवाद ... क्या आप वीक संदर्भों के अलावा समान कार्यक्षमता प्राप्त करने के किसी भी तरीके से सोच सकते हैं? –

+0

@Robert, विनाशकर्ता के रूप के अलावा अन्य/निपटाने मैं मैं बिल्कुल सहमत हैं, वैसे भी, कमजोर घटनाओं चाल कर सकता मेरे सिर – JaredPar

+0

के ऊपर से कुछ भी नहीं सोच सकते हैं! एक छोटा सा पकड़, वे सी # में मौजूद नहीं हैं इसलिए आपको इसे लागू करना होगा (यह थोड़ा मुश्किल है लेकिन मूल रूप से संभव है)। –

0

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

वास्तविक डिजाइन समस्या क्या है जिसे आप हल करना चाहते हैं? एक बेहतर तरीका हो सकता है।

+0

मैं एक ऐसी प्रणाली बनाना चाहता हूं जहां ऑब्जेक्ट्स को कभी-कभी सर्वर पर क्रमबद्ध करने के लिए पंजीकृत किया जाता है। धारावाहिक डेटा हर कुछ मिनट (मेरे नियंत्रण से बाहर) सर्वर पर धकेल दिया जाएगा, इसलिए आमतौर पर सभी पंजीकृत वस्तुओं के क्रमबद्ध डेटा की गणना की जाती है। हालांकि, यदि एक पंजीकृत ऑब्जेक्ट को नष्ट किया जा रहा है, तो मैं मरने से पहले डेटा की गणना करना चाहता हूं (और वह डेटा सर्वर पर अगले बैच के साथ भेजा जाएगा)। –

+2

वह अभी भी थोड़ा मजेदार लगता है। आप समय-समय पर एक सर्वर अप करने के लिए धारावाहिक डेटा भेजने के लिए जा रहे हैं, तो क्यों न सिर्फ वस्तु जिम्मेदार है कि क्रमबद्धता के लिए पंजीकृत वस्तुओं के लिए एक (nonweak) संदर्भ बनाए रखने, और उन्हें जारी एक बार वे अपलोड किया गया है है? विनाश समय की अप्रत्याशितता को देखते हुए, आप डेटा अखंडता के लिए वैसे भी इस पर निर्भर नहीं रहना चाहेंगे। –

+0

उन्हें जीवित/बदलते समय तक हर बार क्रमबद्ध होने की आवश्यकता होती है। यह सिल्वरलाइट यूआई वरीयताओं (यानी कॉलम चौड़ाई, इत्यादि) है, इसलिए जब तक यूआई तत्व अभी भी आसपास हैं, उनके राज्य को सर्वर पर सहेजने की जरूरत है। –

0

जो आप वर्णन कर रहे हैं, उसके लिए फाइनल बेहतर होगा दृष्टिकोण।

0

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

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

दुर्भाग्य से, मैं इस तरह की रणनीति के किसी भी पूरा कार्यान्वयन नहीं देखा है। विचार करने के लिए कुछ महत्वपूर्ण चेतावनी हैं। उनमें से: (1) फाइनलरों को ताले पर कभी इंतजार नहीं करना चाहिए, न ही कुछ भी जो अपवाद फेंक सकता है; (2) कोड है जो अन्य वस्तुओं की संभावना है कि वे पहले से ही अंतिम रूप दे दिया गया हो सकता है के लिए तैयार रहना चाहिए क्षेत्र से बाहर चले गए हैं हो सकता है पहुंचता है, तो अंतिम रूप दिया जा रहा है की प्रक्रिया में हो सकता है, अंतिम रूप दिए जाने का इंतजार कर रहा हो, या अभी भी कहीं और लाइव संदर्भ है, (3) यदि कोई फाइनेंजर एक अंतिम वस्तु के रूट संदर्भ को संग्रहीत करता है जो कचरा संग्रह के लिए योग्य पाया गया है, तो लाइव ऑब्जेक्ट मौजूद होने के बावजूद ऐसी वस्तु को अंतिम रूप दिया जा सकता है।

6

नेट 4.0 समाधान की जरूरत है: ConditionalWeakTable। यहां एक छोटा कार्यक्रम है जो विचार को प्रदर्शित करता है। (here पर भी चर्चा की गई)

using System; 
using System.Runtime.CompilerServices; 

namespace GCCollectNotification 
{ 
    class ObjectToWatch { } 

    class Notifier 
    { 
     public object ObjectToWatch { get; set; } 
     ~Notifier() { Console.WriteLine("object is collected"); } 
    } 

    class Program 
    { 
     private ConditionalWeakTable<object, Notifier> map 
      = new ConditionalWeakTable<object, Notifier>(); 

     public void Test() 
     { 
      var obj = new ObjectToWatch(); 
      var notifier = map.GetOrCreateValue(obj); 
      notifier.ObjectToWatch = obj; 
     } 

     static void Main(string[] args) 
     { 
      new Program().Test(); 

      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      // "object is collected" should have been printed by now 

      Console.WriteLine("end of program"); 
     } 
    } 
}