2012-03-02 14 views
5

मैं गुमनाम ईवेंट हैंडलर्स के बारे में एक नहीं बल्कि छोटे सवाल है:बेनामी घटना संचालकों और निपटान

इस कोड है कि मैं है:

public void AddTestControl(Control ctrl) 
{ 
    ctrl.Disposed += (o, e) => { RemoveTestControl(ctrl); }; 
    ctrl.SomeEvent += _Control_SomeEvent; 
} 

public void RemoveTestControl(Control ctrl) 
{ 
    ctrl.SomeEvent -= _Control_SomeEvent; 
} 

ठीक ऊपर यह कोड है, या कोड होना चाहिए विस्थापित घटना हैंडलर को हटाने के लिए फिर से लिखा जाना चाहिए? कुछ इस तरह:

public void AddTestControl(Control ctrl) 
{ 
    ctrl.Disposed += _Control_Disposed; 
    ctrl.SomeEvent += _Control_SomeEvent; 
} 

public void RemoveTestControl(Control ctrl) 
{ 
    ctrl.Disposed -= _Control_Disposed; 
    ctrl.SomeEvent -= _Control_SomeEvent; 
} 

उत्तर

8

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

इस मामले में, यह मानते हुए WebForms या WinForms है, प्रकाशक (कि Control वस्तु है), सबसे अधिक संभावना ग्राहक (शायद एक Page या एक Form) के एक बच्चे वस्तु, जो पहले हो जाएगा अपने सभी संबंधित वस्तुओं को इसके साथ ले जाने के दायरे से बाहर निकलने के लिए। इसलिए ईवेंट हैंडलर को हटाने की कोई आवश्यकता नहीं है। घटना फिर से उठाया जा कभी नहीं होगा,:

+0

afaik कोई भी ईवेंट हैंडलर के निष्पादन आदेश का वादा नहीं करता है। – b0rg

+0

लेकिन मेरा प्रश्न विवादित घटना के बारे में अधिक है। क्या मुझे इसे खुद को अलग करने की आवश्यकता है या पहला कोड नमूना ठीक है? – juFo

+1

@juFo मान लीजिए कि आप जो कारण पूछते हैं वह है क्योंकि आप मेमोरी लीक के बारे में चिंतित हैं, तो ** नहीं, आपको ईवेंट हैंडलर को अलग करने की आवश्यकता नहीं है **। चूंकि 'नियंत्रण' ऑब्जेक्ट में 'पृष्ठ' या 'फॉर्म' का एक ही जीवनकाल होता है जिसमें ईवेंट हैंडलर होते हैं, वे एक साथ गुंजाइश से बाहर निकल जाएंगे। –

2

यह हमेशा , घटनाओं से सदस्यता समाप्त करने भी स्थितियों में, जहां मैं ग्राहकों पता हमेशा से अधिक जीवित प्रकाशक (वस्तु घटना को ऊपर उठाने) मेरे लिए क्लीनर लगता है प्रकाशक अब तक पहुंच योग्य नहीं है और इसे एकत्रित किया जा सकता है।

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

यदि आप सदस्यता समाप्त करना चाहते हैं, तो एक ही प्रतिनिधि को सदस्यता समाप्त करने की आवश्यकता अज्ञात घटना हैंडलर को दर्द का थोड़ा सा बनाता है। Reactive Extensions इस समस्या को एक साफ तरीके से हल करें: आपके द्वारा सब्सक्राइब किए गए प्रतिनिधि को याद रखने के बजाय, सदस्यता लेने पर IDisposable रिटर्न सदस्यता लेता है जो डिस्पोजेक्ट करते समय सदस्यता रद्द करता है। CompositeDisposable में अपनी सभी सब्सक्रिप्शन को चकित करने से आप केवल एक Dispose कॉल के साथ सबकुछ सदस्यता ले सकते हैं।

1

दोनों कोडेज़ ठीक हैं, लेकिन मुझे व्यक्तिगत वरीयता के मामले में दूसरा पसंद है। यह पहले की तुलना में स्पष्ट पढ़ता है।

पहले कोड के साथ इसके ऊपर, अज्ञात लैम्ब्डा प्रतिनिधि है और इसे ctrl का वर्तमान संदर्भ मिलता है। वह कोड स्थिति के आधार पर अप्रत्याशित रूप से व्यवहार कर सकता है और ऑप्टिमाइज़ेशन सेटिंग्स संकलित कर सकता है: कॉल को रेखांकित किया गया है या नहीं।

उल्लेख नहीं है कि कोड के साथ वास्तुशिल्प समस्या है: आपके पास ControlOwner और बाल नियंत्रण का एक गुच्छा है।मैं इसे लेता हूं आप रनटाइम पर ControlOwner पर बाल नियंत्रण जोड़ रहे हैं, और उसके बाद ControlCwner को बच्चे नियंत्रण घटनाओं की सदस्यता ले कर अपने व्यवहार पर प्रतिक्रिया करने का प्रयास कर रहे हैं। यह _ButtonClicked आदि जैसी घटनाओं के लिए ठीक है लेकिन निपटान के लिए अच्छा नहीं है। बच्चे को नियंत्रित करने के लिए इसे अपने आप को निपटाने दें, मालिक नियंत्रण को इसके बारे में जानने की आवश्यकता नहीं है। उल्लेख नहीं है कि यह चाइल्डकंट्रोल [एन] में मौजूद नहीं हो सकता है। उद्देश्य कहा जाता है।

संक्षेप में: * अकेले चाइल्डकंट्रोल पर निपटान कार्यक्रम छोड़ना और चाइल्डकंट्रोल में सभी को साफ करना बेहतर है। का पालन करें * घटनाओं से सदस्यता समाप्त करना आवश्यक नहीं है। इवेंट डिस्पैचर जांच करेगा कि क्या ग्राहक जिंदा है या नहीं।

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