2012-03-30 22 views
7

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

using System; 
using System.Diagnostics; 
using System.Threading; 


namespace DestructorTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      new DestructorTest(); 
      new LoopDestructorTest(); 
      using (new DisposableTest()) { } 
     } 
    } 

    class DestructorTest 
    { 
     ~DestructorTest() 
     { 
      // This isn't allowed to finish. 
      Thread.Sleep(10000); 
     }  
    } 

    class LoopDestructorTest 
    { 
     ~LoopDestructorTest() 
     {   
      int cur = 0; 
      for (int i = 0; i < int.MaxValue; ++i) 
      { 
       cur = i; 
      } 
      // This isn't allowed to finish. 
      Debug.WriteLine(cur); 
     } 
    } 

    class DisposableTest : IDisposable 
    { 
     public void Dispose() 
     { 
      // This of course, is allowed to finish. 
      Thread.Sleep(10000); 
     } 
    } 
} 

तो, विनाशकर्ता का चलना पूर्ण होने की गारंटी नहीं कर रहे हैं?

+3

किसी अन्य ऑब्जेक्ट से किसी ऑब्जेक्ट की समाप्ति के लिए प्रतीक्षा करना? यह पागलपन है! – MattDavey

+0

विश्वसनीय विनाश और संसाधन रिलीज के लिए आपको वास्तव में 'आईडीस्पोजेबल' पैटर्न के साथ रहना चाहिए। –

+0

@MattDavey ... और किसी अन्य ऑब्जेक्ट से किसी ईवेंट की प्रतीक्षा करना जारी रखने के लिए 'निपटान()' पागलपन नहीं है? क्या फर्क पड़ता है? –

उत्तर

15

तो क्या विनाशक दौड़ने की गारंटी नहीं दे रहे हैं?

मैं क्या याद है, जब प्रक्रिया समाप्त हो जाता है यह finalizers निष्पादित करने के लिए कुछ सेकंड देता है, लेकिन फिर प्रक्रिया अचानक समाप्त हो जाता है से सं। आप एक प्रक्रिया को रोकने के लिए एक बुरा फाइनलर नहीं चाहते हैं, क्या आप?

आप एक "सबसे अच्छा प्रयास" क्लीन-अप के रूप में अंतिम रूप दिए जाने के संबंध में होना चाहिए - विशेष रूप से, यह नहीं ऐसे बीएसओडी या बिजली कटौती के रूप में स्थितियों में, जहां पूरी व्यवस्था अचानक बंद हो जाता है, में होने जा रहा है।

संपादित करें:

एक ताला चल रहे सभी धागे को रोकने की प्रक्रिया में अनाथ था, तो, बंद कोड पथ के लिए असफल हो जायेगी: मैं एक blog post from Joe Duffy के रूप में कुछ छद्म प्रलेखन पाया है ताला हासिल करें। यदि इन अधिग्रहणों को गैर-टाइमआउट (या लंबे समय तक) के साथ किया जाता है, तो एक लटका होगा। इस से निपटने के लिए (और किसी अन्य प्रकार की लटक जो हो सकती है), सीएलआर फाइनलज़र थ्रेड पर नजर रखने के लिए वॉचडॉग थ्रेड की घोषणा करता है। हालांकि कॉन्फ़िगर करने योग्य, डिफ़ॉल्ट रूप से सीएलआर फाइनलाइज़र को अधीर होने से पहले 2 सेकंड तक चलाएगा; यदि यह टाइमआउट पार हो गया है, तो फाइनलज़र थ्रेड बंद कर दिया गया है, और शटडाउन शेष फाइनेंजर कतार को निकाले बिना जारी रहता है।

+1

असल में मैं विजुअल स्टूडियो में बड़ी चेतावनी प्राप्त करना चाहता हूं, एप्लिकेशन को सही तरीके से अंतिम रूप नहीं दिया गया था (जैसा कि सभी विनाशकों को खत्म करने की अनुमति नहीं थी चल रहा है)। –

+6

@ स्टेवेनज्यूरिस: ऐसा लगता है कि आप उस परिस्थिति में फाइनलाइजर्स पर भरोसा कर रहे हैं जहां आपको वास्तव में * नहीं होना चाहिए। फाइनेंजर्स को संसाधन लीक से बचने के लिए * सहायता * चाहिए - यदि आपका सिस्टम खराब स्थिति में समाप्त हो जाएगा यदि वे पूरा होने के लिए नहीं चलते हैं, तो आपको फिर से डिजाइन करना चाहिए। आखिरकार, संभावना है कि वे बीएसओडी, पावर आउटेज इत्यादि के कारण * नहीं चलेंगे। –

+0

वैसे पाठ्यक्रम के रीडिज़ाइन में 'आईडीस्पोजेबल' का उपयोग करना शामिल है, जिसे अचानक समाप्त नहीं किया जाता है क्योंकि इसे एक्स एमएस का इंतजार करना पड़ता है एक घटना जो एक निपटान चरण इंगित करती है समाप्त हो जाती है और अगला कदम निष्पादित किया जा सकता है। मैं बस विनाशकों के बिंदु को नहीं देखता हूं। किस स्थिति में _should_ आप उन पर भरोसा करते हैं? –

1

तो, विनाशकर्ता का चलना पूर्ण होने की गारंटी नहीं कर रहे हैं?

हालांकि इसकी उदाहरणों नहीं अपने कोड में नहीं हो सकता है, जहां एक GC.SuppressFinalize स्पष्ट Dispose() विधि से कहा जाता है

। यह अंतिमकरण को दबाता है, और उन वस्तुओं के लिए है जिनकी आवश्यकता नहीं है।

यह प्रदर्शन में काफी सुधार कर सकता है, क्योंकि अंतिम वस्तुएं हमेशा एक कचरा संग्रह में बनी रहेंगी, यानी इसे जीन 1 या यहां तक ​​कि जीन 2 जीसी में भी बढ़ावा दिया जाएगा, जिसमें इससे अधिक लागत जुड़ी हुई है।

1

.NET विनाशकों के साथ नहीं आता है। आपके कोड में फाइनलाइजर्स इसके बजाय है।

ऑब्जेक्ट्स कचरा इकट्ठा होने पर फाइनल को बुलाया जाता है, जब इसे हटाया जाता है। उन्हें लटकाने वाली वस्तुओं को रोकने के लिए सीमित निष्पादन समय भी मिलता है।

https://en.wikipedia.org/wiki/Finalizer भी देखें।

+1

लेकिन सी # निश्चित रूप से [विनाशक] है (http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx) –

+0

सी # spec लिखने वाले लोगों ने यह आदेश दिया है कि सिंटैक्टिकल तत्व एक टिल्डे के साथ इंगित करता है जिसके बाद एक वर्ग का नाम आधिकारिक तौर पर एक विनाशक कहा जाता है। मुझे लगता है कि विनाशक वाक्यविन्यास और शब्दावली दोनों मूर्ख हैं, क्योंकि (1) "विनाशक" शब्द का इस्तेमाल पहले से ही अन्य भाषाओं द्वारा किया गया था, जिसका मतलब कुछ अलग और असंबंधित था; (2) शब्द "फाइनलाइज़र" मौजूद है और वर्णन करता है कि सी # विनाशक आम तौर पर क्या करने की कोशिश कर रहा है, हालांकि एक विनाशक किसी अन्य कोड में फाइनलर को लपेटता है; (3) एक विनाशक के उचित उपयोग के लिए आम तौर पर 'जीसी.SuppressFinalize() 'और' GC.KeepAlive() ' – supercat

+0

की आवश्यकता होती है ... इसलिए जब तक कि दो कार्यक्षेत्रों का समर्थन करने वाले ढांचे को मौजूद न करें लेकिन कुछ विधि के माध्यम से अंतिम रूप दें 'ऑब्जेक्ट। फाइनलाइज 'को ओवरराइड करने के अलावा, एक विनाशक का उपयोग' ऑब्जेक्ट। फाइनलाइज 'ओवरराइड करने से अधिक पोर्टेबल नहीं है, अगर सी # ने कार्रवाई के बाद के पाठ्यक्रम की अनुमति दी है। – supercat

0

देखने का एक और तरीका यह है कि कचरा कलेक्टर स्मृति को मुक्त करते समय अंतिमकर्ता कहा जाता है।

हालांकि यदि आपके पास ऐसा प्रोग्राम था जो 1 एमबी मेमोरी के लिए आवश्यक था लेकिन 10 एमबी मेमोरी वाली मशीन पर चल रहा था तो एक कलेक्टर कलेक्टर का वैध कार्यान्वयन कुछ भी नहीं करेगा (क्योंकि कार्यक्रम के लिए पर्याप्त स्मृति होगी निष्पादन हेतु)। उस स्थिति में कोई फाइनलर कभी नहीं कहा जाएगा।