2011-11-22 63 views
5

संभव डुप्लिकेट:
Timer, event and garbage collection : am I missing something?क्यों स्थानीय कब्जा टाइमर गुंजाइश से बाहर नहीं होगा?

private void TrayForm_Load(object sender, EventArgs e) 
{ 
    System.Timers.Timer HideMeTimer = new System.Timers.Timer(2500); 
    HideMeTimer.Elapsed += 
     delegate(object sender2, System.Timers.ElapsedEventArgs e2) 
     { 
      this.Invoke(new Action(somestuff)); 
     }; 
     HideMeTimer.Start(); 
     GC.Collect(); 
} 

किसी कृपया मुझे दिखा सकते हैं कैसे compilator इस अनुवाद करेगा? या अच्छी व्याख्या क्यों लोडर घटना के बाद टाइमर टिक टिकते रहते हैं।

(जब अंतिम संदर्भ चला गया है एक चर करने के लिए, नियम नहीं है, जीसी कुछ समय वस्तु मार डालेगा!)

+1

यहां तक ​​कि अगर संदर्भ एकत्र किया जा सकता है, तो यह नहीं हो सकता है, ** आपके पास चर के दायरे से बाहर होने से पहले एकत्र करने के लिए कॉल है। ** संग्राहक कुछ भी इकट्ठा करने वाला नहीं है जो अभी भी दायरे में है। (जिटर को * अनुमति है * यह समझने के लिए कि चर के लिए अंतिम संदर्भ कॉल करने से पहले है, और इसे एकत्र करने की अनुमति है, लेकिन * सामान्य रूप से * आपकी तकनीक को कोई समझ नहीं आता है; आपको जिटर पर भरोसा नहीं करना चाहिए कलेक्टर को उन चीजों को इकट्ठा करने के लिए कह रहे हैं जो अभी भी गुंजाइश हैं! –

+0

सच - धन्यवाद! – Niklas

+0

इस प्रश्न को कई बार पूछा गया है; दाईं ओर से संबंधित "अनुभाग" अनुभाग देखें। संक्षिप्त उत्तर यह है कि टाइमर विशेष हैं; वे खुद को जीवित रखते हैं। अन्यथा वे बहुत बेकार होंगे; संभवतः आप एक टाइमर बनाते हैं क्योंकि आप इसे टिक रखना चाहते हैं। –

उत्तर

10

आप समझने के लिए System.Timers.Timer पर्दे के पीछे क्या कर रहा है की जरूरत है। यह System.Threading.Timer कक्षा के चारों ओर एक रैपर है। जब टाइमर शुरू होता है तो यह एक नया System.Threading.Timer उदाहरण बनाता है और इसे System.Timers.Timer उदाहरण में कॉलबैक विधि पास करता है। जब तक टाइमर सक्षम रहता है तब तक सिस्टम इस कॉलबैक प्रतिनिधि को संदर्भित करता है।

हम यह भी जानते हैं कि प्रतिनिधि लक्ष्य विधि वाले वर्ग के उदाहरण का संदर्भ रखते हैं। यही कारण है कि आपका System.Timers.Timer उदाहरण एकत्र नहीं किया गया है और स्वचालित रूप से बंद नहीं होता है। Elapsed ईवेंट हैंडलर को हटाने से इस समस्या का समाधान नहीं होगा क्योंकि प्रतिनिधि केवल TrayForm उदाहरण का संदर्भ रखता है। दोबारा, यह System.Threading.Timer है जो System.Timers.Timer का संदर्भ रख रहा है। संपूर्ण संदर्भ श्रृंखला रूट बनी हुई है क्योंकि सिस्टम को काम करने के लिए System.Threading.Timer का संदर्भ देना है।

System => _TimerCallback => Callback => System.Threading.Timer => Callback => System.Timers.Timer 

जब आप इस परावर्तक के साथ के माध्यम से ट्रैक या ILSpy आप देख सकते हैं कि "सिस्टम" संदर्भ श्रृंखला में ऊपर TimerBase.AddTimerNative तरीका है जिसके MethodImplOptions.InternalCall चिह्नित है के माध्यम से खेलने में आता है:

यहाँ संदर्भ श्रृंखला है इसलिए हम वास्तव में नहीं देख सकते कि इस बिंदु के नीचे संदर्भ कैसे रूट किया गया है। लेकिन, फिर भी यह जड़ है।

आप Enabled = false या Stop के माध्यम से टाइमर अक्षम करते हैं तो यह अंतर्निहित System.Threading.Timer जो बदले में करना चाहिए System.Timers.Timer संदर्भित रोक निपटाने होंगे।

+1

-1? अगर कोई मेरे उत्तर में गलत कथन देखता है तो मुझे बताएं। मेरे पास है बीएलएल कोड की जांच करके बीएलएल कोड की जांच करके मेरे जवाब की जांच की गई, लेकिन यह संभव है कि मुझे कुछ याद आया। –

+1

सुनिश्चित नहीं है कि किसने डाउनवॉट किया, लेकिन आप स्पॉट पर हैं। मैंने 'AddTimerNative' के स्रोत पर एक त्वरित झलक लिया और यह वास्तव में '_TimerCallBack' प्रतिनिधि के लिए एक जीसी रूट बनाता है। – dlev

+0

@dlev: उसमें खुदाई के लिए धन्यवाद। मैं सोच रहा था कि 'AddTimerNative' कॉलबैक को "रूट" करने जा रहा था। बहुत सूचनाप्रद। –

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