2010-03-28 12 views
12

क्या किसी दिए गए ईवेंट की सदस्यता लेने वाले सभी हैंडलरों को फिर से शुरू करने का कोई आसान तरीका है? मेरी समस्या यह है कि ग्राहक सब्सक्राइब करते हैं लेकिन सदस्यता समाप्त करना भूल जाते हैं ताकि स्मृति रिसाव हो। मुझे किसी ऑब्जेक्ट को निपटान विधि में अपने ईवेंट के सभी हैंडलरों को डिस्कनेक्ट करने का एक तरीका चाहिए ताकि एक रिसाव न हो - कम से कम घटनाओं के कारण नहीं।सी # किसी दिए गए ईवेंट से सभी ईवेंट हैंडलर को कैसे सदस्यता रद्द करें?

उत्तर

11

सेट अपने इवेंट में अशक्त: MyEvent = null;

लेकिन यह वास्तव में अपने घटना से सदस्यता समाप्ति ग्राहकों बनाने के लिए बेहतर है।

+1

यह शून्य पर एक घटना सेट करने के लिए सी # में संभव नहीं है। –

+8

असल में यह संभव है, अगर आप कक्षा के अंदर हैं जहां ईवेंट घोषित किया गया था। –

+1

आप सही हैं। –

9

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

यह आमतौर पर ग्राहकों को "भूल" एक .NET घटना से सदस्यता समाप्त करने के साथ समस्या को हल करने के लिए इस्तेमाल किया जाता है, तो यह लगता है इस तरह अच्छी तरह से अपनी समस्या के लिए अनुकूल हो सकता है।

  • ड्यूजिंग कैंपबेल का अच्छा article about weak delegates है।
  • मुझे यह overview at CodeProject भी पसंद आया, जो अधिकांश परिदृश्यों पर चर्चा करता है।
  • Weak Events का उपयोग WPF में भी किया जाता है, लेकिन यह दृष्टिकोण थोड़ा जटिल लगता है (मेरे लिए)।
7

मेमोरी लीक केवल तब होता है जब कोई अन्य ऑब्जेक्ट (श्रोता) आपके ऑब्जेक्ट (ईवेंट स्रोत) से पहले मर जाता है। इस मामले में, ईवेंट स्रोत अभी भी श्रोता के संदर्भ को रखता है, जो श्रोता को एकत्रित करने से रोकता है। जब ईवेंट स्रोत मर जाता है, तो सदस्यता रहित श्रोता भी एकत्र किया जा सकता है।

घटना स्रोत श्रोता से पहले मर जाता है, तो यह श्रोता नहीं रोकता है बाद में एकत्र होने के लिए, जब यह करने के लिए अन्य सभी संदर्भों को शून्य पर सेट कर रहे हैं।

इसका मतलब है, घटना स्रोत निपटान विधि इस समस्या को हल करने के लिए सही जगह नहीं है। इसे केवल श्रोता कोड में हल किया जा सकता है। बस बात कर रहे हैं, आप अपने ग्राहकों को स्वच्छ कोड लिखने के अलावा, कुछ भी नहीं कर सकते हैं।

1

लेखन के समय, सबसे सटीक उत्तर कम से कम लोकप्रिय है।

आप ईवेंट हैंडलर को रद्द कर सकते हैं लेकिन इसके मालिक को ज़ेड किए जाने के बाद भी इसे ज़ेड किया जाएगा - यह बहुत साफ नहीं है, लेकिन एलेक्स की तरह, यह मुद्दा नहीं है।

एडी का स्रोत वर्ग श्रवण वस्तुओं को इकट्ठा होने की अनुमति देगा, इसमें कोई संदेह नहीं है। तो समस्या यह है कि एडी के स्रोत वस्तु को अपने ग्राहक के कोड में संदर्भों की कुछ लंबी श्रृंखला से संभवतः खुला रखा जा रहा है।

निम्न ब्लॉग पोस्ट यह भी एक समाधान को देखता है कि एडीई बता रहा है और बताता है कि यह अनावश्यक क्यों है।

http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx

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