2012-05-18 14 views
7

साथ बिना क्रिया का अपवाद के बाद नहीं कहा मैं इस तरह परीक्षण कोड है:finalizer भी CriticalFinalizerObject

public class A : CriticalFinalizerObject 
{ 
    ~A() 
    { 
     File.WriteAllText("c:\\1.txt", "1z1z1"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(); 
     throw new Exception(); 
    } 
} 

सबसे पहले मैं CriticalFinalizerObject से एक पाने के बिना इसे चलाने की कोशिश की। इस कार्यक्रम के अंत के बाद फाइनलाइज़र को नहीं बुलाया गया था। मुझे आश्चर्य हुआ क्योंकि मैंने सोचा कि यह अधिक निर्धारक था लेकिन ठीक है। फिर मैंने क्रिटिकलफिनलाइज़र ऑब्जेक्ट्स के बारे में पढ़ा है जो सुनिश्चित करता है कि उनके फाइनलरों को बुलाया जाएगा। मैंने इससे ए व्युत्पन्न किया। क्या सोचो। यह अभी भी निष्पादित नहीं किया गया है। मैं गलत क्या कर रहा/समझ रहा हूं?

(, मैं जानता हूँ कि कृपया के बारे में कचरा कलेक्टर की जा रही गैर नियतात्मक स्पष्ट सामान न लिखें। यह मामले के रूप में कार्यक्रम खत्म हो गया है और मैं कल्पना मैं सुरक्षित रूप से करने के बाद एक अच्छा बिना क्रिया कामयाब अपवाद को साफ कर सकता है नहीं है ।)

उत्तर

9

सबसे पहले नहीं किया है,, के MSDN में के बारे में CriticalFinalizerObject पढ़ने देती हैं, हम पढ़ सकते हैं कि:

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

यहां मुख्य शब्द संयुक्त है।

दूसरे, के MSDN फिर से पढ़ने देती हैं, प्रबंधित धागे में अपवाद के बारे में इस समय:

इन अपवादों या धागे कि अप्रबंधित कोड से क्रम में प्रवेश में मुख्य थ्रेड में बिना क्रिया कर रहे हैं, वे आम तौर पर आगे बढ़ना, जिसके परिणामस्वरूप आवेदन के समाप्त हो गया।

मुख्य शब्द टर्मिनल है।

तो, जब मुख्य थ्रेड में एक अनचाहे अपवाद होता है - ऐप समाप्त हो जाता है, लेकिन CriticalFinalizerObject केवल डोमेन को उतारने में मदद करता है।

उदाहरण के लिए, CriticalFinalizerObject कर सकते हैं ऐसी स्थिति में मदद करता है:

// Create an Application Domain: 
AppDomain newDomain = AppDomain.CreateDomain("NewApplicationDomain"); 

// Load and execute an assembly: 
newDomain.ExecuteAssembly(@"YouNetApp.exe"); 

//Unload of loaded domain 
AppDomain.Unload(newDomain); 

यह एक ऐसी स्थिति है, जहां डोमेन उतारा गया है, और आप की गारंटी CriticalFinalizerObject, जो आपके finalizer बुलाया जाएगा।

अनुप्रयोग के समाप्त साथ अपनी स्थिति में आप

AppDomain.CurrentDomain.UnhandledException 

की सदस्यता के लिए कोशिश कर सकते हैं और मैन्युअल रूप से अपनी वस्तुओं को अंतिम रूप देने।

युपीडी: अपनी पुस्तक "CLR सी # के माध्यम से" में जेफरी रिक्टर CriticalFinalizerObject बारे में लिखा था, कि यह स्थितियों में, जहां आप SQLServer को उदाहरण के लिए अपने कोड भेज है, जो एक प्रक्रियाओं के रूप में सी # चला सकते हैं के लिए है। ऐसे मामले में CriticalFinalizerObject आपको अपनी ऑब्जेक्ट को साफ़ करने में मदद करता है, यदि SQLServer आपके लाइब्रेरी के डोमेन को अनलोड करेगा। इसके अलावा CriticalFinalizerObject उन परिस्थितियों के लिए है जहां आपको किसी अन्य ऑब्जेक्ट की कॉल विधि को ऑब्जेक्ट के अंतिम रूप में करने की आवश्यकता होती है, क्योंकि क्रिटिकलफिनलाइज़र ऑब्जेक्ट आपको गारंटी देता है कि यह सभी गैर-क्रिटिकल फाइनाइज़र ऑब्जेक्ट ऑब्जेक्ट्स के अंतिमकरण के बाद अंतिम रूप दिया जाएगा।

+0

विस्तृत उत्तर के लिए धन्यवाद! मैं कहूंगा कि "समाप्त" बनाम "अनलोडेड" जैसे शब्द इन एमएस दस्तावेज़ों में बहुत अच्छी तरह से परिभाषित नहीं हैं। सामान्य रूप से, कुछ "समाप्त" होने का मतलब यह नहीं है कि यह "अनलोड नहीं किया जाएगा", हालांकि हम देखते हैं कि यह ऐसा नहीं है ... – IlyaP

+0

मैंने "सीएलआर के माध्यम से सी # के जवाब में कुछ अपडेट जोड़े" – igofed

0

ठीक है। एक साधारण परीक्षण लिखा है। यदि मेरे पास कन्स्ट्रक्टर में अपवाद है जहां मैं अपना ऑब्जेक्ट बनाता हूं, वास्तव में काम करने के लिए फाइनलर नहीं कर सका, लेकिन जब मैंने ऑब्जेक्ट बनाया तो अन्य वर्ग के निर्माता में नहीं बल्कि अन्य विधि में, और फिर अपवाद फेंक दिया।

तो मुझे संदेह है कि अगर कन्स्ट्रक्टर कभी कक्षा का निर्माण समाप्त नहीं करता है, और इसकी रचना समाप्त हो जाती है, ऑब्जेक्ट कभी नहीं बनाया जाता है, ढेर साफ़ किया जाता है, ऑब्जेक्ट को ढेर से हटाया जाता है जैसे कि वे कभी नहीं होते हैं।

यह मेरा अनुमान है। लेकिन समस्या को हल करने के लिए, मैं कोशिश करता हूं कि क्रिएटिव क्रिएटिंग कोड ऑब्जेक्ट्स को ऑब्जेक्ट्स को रीक-कैच-एंड-एंड में स्पष्ट रूप से कॉल करें।

उदाहरण: यह

public Form1() 
     { 
      InitializeComponent(); 
     } 
     protected override void OnLoad(EventArgs e) 
     { 
      base.OnLoad(e); 
      var a = new A(); 
      throw new Exception(); 
     } 
    } 

काम किया यह

public Form1() 
     { 
      InitializeComponent(); 
      var a = new A(); 
      throw new Exception(); 
     } 

    } 
+0

इसे कॉल नहीं किया जाता है - जैसा कि आप देखते हैं, मैं फाइनलज़र में एक फाइल बनाता हूं - यह कभी नहीं दिखाई देता है। – IlyaP

+0

जीसी.कोलेक्ट() कहां? अगर अपवाद फेंकने से पहले निश्चित रूप से यह काम करेगा। लेकिन मैं फेंकने के बाद कोई कोड नहीं लिख सकता ... – IlyaP

+1

अनचाहे को संभालने के लिए आप अभी भी 'AppDomain.CurDomain.UnhandledException' ईवेंट' का उपयोग कर सकते हैं। –

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