दिलचस्प पोस्ट
किसी सर्वर पर अपलोड करने से पहले आईफोन ओएस एसडीके पर छवि को कैसे सेकेंड / रीसाइज करना है? विम में हाइलाइट करने वाले वर्ग और फ़ंक्शन के नाम बाश में एक सरणी में विभाजित स्ट्रिंग जब मैं सेटटिमेउट का उपयोग करता हूं तो विधि तुरंत निष्पादित क्यों होती है? सर्वर से प्रमाण पत्र प्राप्त करने के लिए openssl का उपयोग करना स्ट्रिंग पायथन में स्नो शब्द गणना करें क्या हेड, बॉडी और एचटीएमएल टैग लिखना आवश्यक है? ऑपरेटर ओवरलोडिंग और जावा में ओवरराइडिंग SQL सर्वर एक्सप्रेस की सीमाएं हस्केल में 2 सूचियों का कार्टेशियन उत्पाद .NET के HttpWebRequest / Response के साथ एक स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग करना उच्च रिज़ॉल्यूशन अंतराल / टाइमर में ईवेंट बढ़ाएं JSON वर्ण एन्कोडिंग जेयूनेट के साथ ईजेबी का परीक्षण करना C # winforms कॉम्बोबोक्स गतिशील स्वत: पूर्ण

क्यों एक सिस्टम.टीमर्स.टीमर जीसी जीती है लेकिन सिस्टम नहीं। थ्रेडिंग.टीमर?

यह प्रतीत होता है कि System.Timers.Timer उदाहरणों को कुछ तंत्र द्वारा जीवित रखा जाता है, लेकिन System.Threading.TimerSystem.Threading.TimerSystem.Threading.Timer उदाहरण नहीं हैं।

एक आवधिक प्रणाली के साथ नमूना कार्यक्रम। System.Threading.Timer और ऑटो रीसेट System.Timers.Timer :

 class Program { static void Main(string[] args) { var timer1 = new System.Threading.Timer( _ => Console.WriteLine("Stayin alive (1)..."), null, 0, 400); var timer2 = new System.Timers.Timer { Interval = 400, AutoReset = true }; timer2.Elapsed += (_, __) => Console.WriteLine("Stayin alive (2)..."); timer2.Enabled = true; System.Threading.Thread.Sleep(2000); Console.WriteLine("Invoking GC.Collect..."); GC.Collect(); Console.ReadKey(); } } 

जब मैं इस प्रोग्राम (। NET 4.0 क्लाइंट, रिलीज, डिबगर के बाहर) चलाता हूं, तो केवल सिस्टम। थ्रेडिंग। टाइमर जीसी है:

 Stayin alive (1)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Invoking GC.Collect... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... Stayin alive (2)... 

संपादित करें : मैंने नीचे जॉन का जवाब स्वीकार किया है, लेकिन मैं इसके बारे में थोड़ा सा बताना चाहता था।

जब ऊपर नमूना कार्यक्रम चल रहा है ( Sleep में एक ब्रेकपॉइंट के साथ), यहां प्रश्नों और GCHandle तालिका में ऑब्जेक्ट की GCHandle है:

 !dso OS Thread Id: 0x838 (2104) ESP/REG Object Name 0012F03C 00c2bee4 System.Object[] (System.String[]) 0012F040 00c2bfb0 System.Timers.Timer 0012F17C 00c2bee4 System.Object[] (System.String[]) 0012F184 00c2c034 System.Threading.Timer 0012F3A8 00c2bf30 System.Threading.TimerCallback 0012F3AC 00c2c008 System.Timers.ElapsedEventHandler 0012F3BC 00c2bfb0 System.Timers.Timer 0012F3C0 00c2bfb0 System.Timers.Timer 0012F3C4 00c2bfb0 System.Timers.Timer 0012F3C8 00c2bf50 System.Threading.Timer 0012F3CC 00c2bfb0 System.Timers.Timer 0012F3D0 00c2bfb0 System.Timers.Timer 0012F3D4 00c2bf50 System.Threading.Timer 0012F3D8 00c2bee4 System.Object[] (System.String[]) 0012F4C4 00c2bee4 System.Object[] (System.String[]) 0012F66C 00c2bee4 System.Object[] (System.String[]) 0012F6A0 00c2bee4 System.Object[] (System.String[]) !gcroot -nostacks 00c2bf50 !gcroot -nostacks 00c2c034 DOMAIN(0015DC38):HANDLE(Strong):9911c0:Root: 00c2c05c(System.Threading._TimerCallback)-> 00c2bfe8(System.Threading.TimerCallback)-> 00c2bfb0(System.Timers.Timer)-> 00c2c034(System.Threading.Timer) !gchandles GC Handle Statistics: Strong Handles: 22 Pinned Handles: 5 Async Pinned Handles: 0 Ref Count Handles: 0 Weak Long Handles: 0 Weak Short Handles: 0 Other Handles: 0 Statistics: MT Count TotalSize Class Name 7aa132b4 1 12 System.Diagnostics.TraceListenerCollection 79b9f720 1 12 System.Object 79ba1c50 1 28 System.SharedStatics 79ba37a8 1 36 System.Security.PermissionSet 79baa940 2 40 System.Threading._TimerCallback 79b9ff20 1 84 System.ExecutionEngineException 79b9fed4 1 84 System.StackOverflowException 79b9fe88 1 84 System.OutOfMemoryException 79b9fd44 1 84 System.Exception 7aa131b0 2 96 System.Diagnostics.DefaultTraceListener 79ba1000 1 112 System.AppDomain 79ba0104 3 144 System.Threading.Thread 79b9ff6c 2 168 System.Threading.ThreadAbortException 79b56d60 9 17128 System.Object[] Total 27 objects 

जैसा कि जॉन ने अपने जवाब में बताया, दोनों टाइमर GCHandle टेबल में अपने कॉलबैक ( GCHandleGCHandleGCHandle कॉलबैक) को पंजीकृत करते हैं। जैसा कि हंस ने अपनी टिप्पणी में बताया, यह किया जाता है जब भी state पैरामीटर को जीवित रखा जाता है।

जैसा कि जॉन ने बताया, कारण System.Timers.Timer जीवित रखा जाता है, क्योंकि यह कॉलबैक द्वारा संदर्भित है (इसे आंतरिक System.Threading.Timer रूप में पारित किया जाता है। System.Threading.TimerSystem.Threading.Timer ); वैसे ही, हमारे सिस्टम का कारण। थ्रेडिंग। टाइमर जीसी है क्योंकि इसका कॉलबैक इसका संदर्भ नहीं देता है

Console.WriteLine("Stayin alive (" + timer1.GetType().FullName + ")") कॉलबैक के लिए एक स्पष्ट संदर्भ जोड़ना (उदाहरण के लिए, Console.WriteLine("Stayin alive (" + timer1.GetType().FullName + ")") ) जीसी को रोकने के लिए पर्याप्त है

System.Threading.Timer पर एकल-पैरामीटर कन्स्ट्रक्टर का उपयोग करना। टाइमर भी काम करता है, क्योंकि टाइमर तब खुद को state पैरामीटर के रूप में संदर्भित करेगा। निम्नलिखित कोड जीसी के बाद दोनों टाइमर को जीवित रखता है, क्योंकि वे प्रत्येक GCHandle तालिका से उनके कॉलबैक द्वारा संदर्भित हैं:

 class Program { static void Main(string[] args) { System.Threading.Timer timer1 = null; timer1 = new System.Threading.Timer(_ => Console.WriteLine("Stayin alive (1)...")); timer1.Change(0, 400); var timer2 = new System.Timers.Timer { Interval = 400, AutoReset = true }; timer2.Elapsed += (_, __) => Console.WriteLine("Stayin alive (2)..."); timer2.Enabled = true; System.Threading.Thread.Sleep(2000); Console.WriteLine("Invoking GC.Collect..."); GC.Collect(); Console.ReadKey(); } } 

वेब के समाधान से एकत्रित समाधान "क्यों एक सिस्टम.टीमर्स.टीमर जीसी जीती है लेकिन सिस्टम नहीं। थ्रेडिंग.टीमर?"

आप windbg, sos, और !gcroot के साथ इस और इसी तरह के सवालों का जवाब दे सकते हैं

 0:008> !gcroot -nostacks 0000000002354160 DOMAIN(00000000002FE6A0):HANDLE(Strong):241320:Root:00000000023541a8(System.Thre ading._TimerCallback)-> 00000000023540c8(System.Threading.TimerCallback)-> 0000000002354050(System.Timers.Timer)-> 0000000002354160(System.Threading.Timer) 0:008> 

दोनों मामलों में, मूल टाइमर को कॉलबैक ऑब्जेक्ट के जीसी (जीसीएंडल के माध्यम से) को रोका जा सकता है। अंतर यह है कि System.Timers.Timer के मामले में। कॉलबैक प्रणाली को संदर्भित करता है। System.Timers.TimerSystem.Timers.Timer ऑब्जेक्ट (जो एक System.Threading.Timer का उपयोग करके आंतरिक रूप से कार्यान्वित किया जाता है। System.Threading.Timer )

मैं काम के कुछ उदाहरण के कार्यान्वयन को देखने के बाद हाल ही में इस मुद्दे को गॉगलिंग कर रहा था। विल और कुछ प्रयोग कर रहे हैं

यह पता चला है कि क्या System.Threading.Timer जीसीडी है कि आप इसे कैसे निर्माण पर निर्भर करता है !!!

अगर सिर्फ एक कॉलबैक के साथ बनाया गया तो राज्य ऑब्जेक्ट टाइमर ही होगा और यह उसे जीसीडी होने से रोक देगा। यह कहीं भी दस्तावेज नहीं प्रतीत होता है और बिना इसके बिना यह आग बनाने और टाइमर को भूलना बेहद कठिन है।

मैं यह http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8/0/untmp/whidbey/REDBITS/ndp/clr/src/BCL/System/Threading/Timer@cs पर कोड से मिला / 1 / टाइमर @ सीएस

इस कोड की टिप्पणियां यह भी संकेत करती हैं कि कॉलबैक-केवल सीटीओर का उपयोग करना हमेशा बेहतर क्यों होता है यदि कॉलबैक टाइमर ऑब्जेक्ट को नए द्वारा लौटाता है, अन्यथा कोई रेस बग हो सकता है।

टाइमर 1 में आप इसे कॉलबैक दे रहे हैं। टाइमर 2 में आप एक ईवेंट हैंडलर को हुक कर रहे हैं; यह आपके प्रोग्राम वर्ग के संदर्भ को सेट करता है जिसका मतलब है कि टाइमर जीसीड नहीं होगा। चूंकि आप कभी भी टाइमर 1 के मूल्य का उपयोग नहीं करते हैं, (मूल रूप से उसी तरह के रूप में यदि आप var टाइमर 1 = हटा दिया गया है) तो कंपाइलर चर को दूर करने के लिए पर्याप्त स्मार्ट है जब आप जीसी कॉल को दबाते हैं, तो टाइमर 1 को अब और नहीं संदर्भित किया जाता है, इसलिए इसकी 'एकत्रित'

एक कंसोल जोड़ें.अपने जीसी कॉल के बाद टाइमर 1 के गुणों में से एक को आउटपुट करने के लिए और आप नोटिस करेंगे कि यह अब और एकत्र नहीं हुआ है।

एफआईआईआई, जैसा कि एनएटी 4.6 (यदि पहले नहीं है) के रूप में, यह अब सच नहीं होने वाला है। आपका परीक्षण कार्यक्रम, आज चलाए जाने पर, या तो टाइमर होने पर कचरा एकत्रित नहीं होता है

 Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Invoking GC.Collect... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... Stayin alive (2)... Stayin alive (1)... 

जैसा कि मैं system.Threading.Timer के कार्यान्वयन को देखता हूं, ऐसा लगता है कि ऐसा लगता है जैसे। NET का वर्तमान संस्करण सक्रिय टाइमर ऑब्जेक्ट की लिंक सूची का उपयोग करता है और उस लिंक्ड सूची को टाइमरकुएयू के भीतर एक सदस्य चर द्वारा आयोजित किया जाता है (जो कि एक सिंगलटन ऑब्जेक्ट को स्थिर सदस्य चर द्वारा टाइमरकुई में भी जीवित रखा गया था)। नतीजतन, सभी टाइमर के उदाहरणों को तब तक जीवित रखा जाएगा जब तक वे सक्रिय होते हैं।

आप उपयोग कर सकते हैं

 GC.KeepAlive(timer1); 

इस ऑब्जेक्ट पर कचरा संग्रहण को रोकने के लिए