आप वास्तव में अपने एक्सेल एप्लीकेशन ऑब्जेक्ट को सफाई से जारी कर सकते हैं, लेकिन आपको ध्यान रखना होगा।
आपके द्वारा उपयोग किए जाने वाले प्रत्येक COM ऑब्जेक्ट के लिए एक नामित संदर्भ बनाए रखने की सलाह और फिर स्पष्ट रूप से इसके माध्यम से जारी करें Marshal.FinalReleaseComObject()
सिद्धांत में सही है, लेकिन, दुर्भाग्य से, अभ्यास में प्रबंधन करना बहुत मुश्किल है। यदि कोई कभी भी कहीं भी फिसल जाता है और "दो डॉट्स" का उपयोग करता है, या for each
लूप के माध्यम से कोशिकाओं को पुनरावृत्त करता है, या किसी अन्य समान प्रकार की कमांड देता है, तो आपको COM ऑब्जेक्ट्स को अप्रतिबंधित करना और हैंग करना होगा। इस मामले में, कोड में कारण खोजने का कोई तरीका नहीं होगा; आपको आंख से अपने सभी कोड की समीक्षा करनी होगी और उम्मीद है कि इस कारण का पता लगाएं, एक कार्य जो एक बड़ी परियोजना के लिए लगभग असंभव हो सकता है।
अच्छी खबर यह है कि आपको वास्तव में आपके द्वारा उपयोग की जाने वाली प्रत्येक COM ऑब्जेक्ट के लिए नामित चर संदर्भ को बनाए रखने की आवश्यकता नहीं है। इसके बजाय, कॉल करें GC.Collect()
और फिरGC.WaitForPendingFinalizers()
उन सभी (आमतौर पर मामूली) वस्तुओं को जारी करने के लिए जिनके लिए आप एक संदर्भ नहीं रखते हैं, और फिर उन वस्तुओं को स्पष्ट रूप से जारी करते हैं जिन्हें आप नामांकित चर संदर्भ रखते हैं।
आपको अपने नामित संदर्भों को महत्व के रिवर्स ऑर्डर में भी जारी करना चाहिए: पहले ऑब्जेक्ट्स, फिर वर्कशीट, वर्कबुक और फिर अंत में आपकी एक्सेल एप्लिकेशन ऑब्जेक्ट।
उदाहरण के लिए, यह मानते हुए कि आपके पास एक रेंज ऑब्जेक्ट वैरिएबल नाम है xlRng
, एक वर्कशीट वैरिएबल नाम xlSheet
, एक वर्कबुक वैरिएबल नाम xlBook
और एक एक्सेल एप्लिकेशन वैरिएबल नाम है xlApp
, तो आपका क्लीनअप कोड कुछ इस तरह दिख सकता है:
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(xlRng);
Marshal.FinalReleaseComObject(xlSheet);
xlBook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(xlBook);
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
अधिकांश कोड उदाहरणों में आप .NET से COM ऑब्जेक्ट्स को साफ करने के लिए देखेंगे, GC.Collect()
और GC.WaitForPendingFinalizers()
कॉल को इस तरह से TWICE बनाया गया है:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
जब तक आप Visual Studio Tools for Office (VSTO) का उपयोग नहीं कर रहे हैं, तब तक इसकी आवश्यकता नहीं होनी चाहिए, जो कि फाइनल का उपयोग करता है जिसके कारण वस्तुओं की एक पूरी ग्राफ को अंतिम रूप से कतार में बढ़ावा दिया जाता है। इस तरह की वस्तुओं को अगले कचरा संग्रहण तक जारी नहीं किया जाएगा । हालांकि, यदि आप वीएसटीओ का उपयोग नहीं कर रहे हैं, तो आपको कॉल करने में सक्षम होना चाहिए GC.Collect()
और GC.WaitForPendingFinalizers()
सिर्फ एक बार।
मुझे पता है कि स्पष्ट रूप से कॉलिंग GC.Collect()
एक नो-नो है (और निश्चित रूप से इसे दो बार करना बहुत दर्दनाक लगता है), लेकिन ईमानदार होने के लिए इसके आसपास कोई रास्ता नहीं है। सामान्य संचालन के माध्यम से आप छिपी हुई वस्तुओं को उत्पन्न करेंगे जिनके लिए आप कोई संदर्भ नहीं रखते हैं, इसलिए, आप कॉलिंग के अलावा किसी अन्य माध्यम से जारी नहीं कर सकते हैं GC.Collect()
।
यह एक जटिल विषय है, लेकिन यह वास्तव में इसके लिए है। एक बार जब आप अपनी सफाई प्रक्रिया के लिए इस टेम्पलेट को स्थापित कर लेते हैं, तो आप सामान्य रूप से, रैपर आदि की आवश्यकता के बिना कोड कर सकते हैं, :-)
मेरे पास इस पर एक ट्यूटोरियल है:
VB.Net / COM इंटरॉप के साथ ऑफिस प्रोग्राम को स्वचालित करना
यह VB.NET के लिए लिखा गया है, लेकिन इसे बंद न करें, सिद्धांत सी # का उपयोग करते समय बिल्कुल समान हैं।