होने से कचरा कलेक्टर को रोकने मैं कोडक्यों ईवेंट हैंडलर्स
public class Publisher
{
public event EventHandler SomeEvent;
}
public class Subscriber
{
public static int Count;
public Subscriber(Publisher publisher)
{
publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
}
~Subscriber()
{
Subscriber.Count++;
}
private void publisher_SomeEvent(object sender, EventArgs e)
{
// TODO
}
}
के इस टुकड़े अपने आवेदन की मुख्य विधि में है मैं
static void Main(string[] args)
{
Publisher publisher = new Publisher();
for (int i = 0; i < 10; i++)
{
Subscriber subscriber = new Subscriber(publisher);
subscriber = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Subscriber.Count.ToString());
}
है, तो मैं इस चलाने के लिए, मैं के रूप में 0 होगा उत्पादन। जो 10
है GC.Collect() बुलाया जा रहा है, जीसी कचरा संग्रहण शुरू करने के लिए मजबूर किया जा रहा है जब - अगर मैं कोड से घटना सदस्यता निकालने के लिए, मैं उम्मीद कर परिणाम मिला होगा। क्योंकि सब्सक्राइबर अंतिम रूप उस में परिभाषित किया गया है, जी सी संग्रह को निलंबित कर देगा जब तक finalizequeue खाली है - जो है के बाद सभी सदस्यता उदाहरणों अपनी अंतिम रूप फोन करेगा() विधियों (कृपया मुझे ठीक कर लें मेरी मान्यताओं गलत कर रहे हैं)। अगली पंक्ति जीसी.WaitForPendingFinalizers() कहा जाता है जिसे अंतिम रूप से निष्पादन को निलंबित कर दिया जाएगा जब तक कि अंतिम कतार खाली न हो जाए। अब, क्योंकि हमारे पास आउटपुट के रूप में 0 है, मुझे लगता है कि अंतिम रूप() को कॉल नहीं किया जा रहा है, जो मुझे विश्वास दिलाता है कि जीसी ने ग्राहकों के उदाहरणों को एकत्रित नहीं किया है, इस प्रकार फ़ाइनलाइज़र() विधियों को नहीं कहा जा रहा है।
तो मैं 2 सवाल
- मेरी धारणा सही और घटना सदस्यता जीसी ग्राहक उदाहरणों चिह्नित करने के लिए एकत्र होने के लिए रोकता है?
- यदि ऐसा है, तो ऐसा इसलिए है क्योंकि प्रकाशक को ग्राहक का संदर्भ है? (Garbage collector and event handlers)
मेरी केवल अनुमान के बाद से वहाँ सब्सक्राइबर के 10 उदाहरणों कि एक ही प्रकाशक उदाहरण के लिए संदर्भित कर रहे हैं कर रहे हैं, जब जी सी संग्रह होता है, यह देखता है कि वहाँ, प्रकाशक को अन्य संदर्भ हैं कि इस प्रकार यह नहीं कर सकता है एकत्रित किया जाए, और नतीजतन प्रकाशक के साथ सभी सब्सक्रिप्शन उदाहरण अगली पीढ़ी में स्थानांतरित किए जा रहे हैं, इसलिए कचरा संग्रह नहीं होता है और न ही अंतिमकरण() को कोड निष्पादन कंसोल पर पहुंचा जा रहा है। साइटलाइन (सब्सक्राइबर .Count.ToString())
क्या मैं सही हूं या क्या मुझे यहां कुछ याद आ रही है?
इस तरह से इसके बारे में सोचो: जब 'Publisher.SomeEvent' प्रतिनिधि बुलाया जा रहा है यह निष्पादित करेंगे जो कुछ भी कॉल के समय यह करने के लिए सदस्यता लिया है। इसका मतलब यह है कि सदस्यता सक्रिय होने पर ग्राहक उदाहरण जीवित रहना पड़ता है। यही कारण है कि प्रकाशक को सभी ग्राहकों का संदर्भ रखना है। चूंकि ग्राहक पहुंच योग्य हैं जीसी उन्हें एकत्र नहीं कर सकते हैं। –