2012-11-20 17 views
10

का कारण बनता है मैं बहुत व्यस्त एक्सेल कार्यपुस्तिकाओं का एक सेट खोलने के लिए COM इंटरऑप लाइब्रेरी के साथ सी # का उपयोग करने की कोशिश कर रहा हूं। मुझे सी # का उपयोग करना है, क्योंकि मुझे मैक्रोज़ शुरू करने, आसपास के कुछ हिस्सों को स्थानांतरित करने और मेरी कंपनी के उपयोग में एक कस्टम एक्सेल-एड-शुरू करने की आवश्यकता है।सी # एक्सेल स्वचालन एक्सेल मेमोरी लीक

मेरा प्रोग्राम तब बाहर निकलता है, कार्यपुस्तिकाओं को खुला छोड़ देता है, प्रत्येक एक अलग एक्सेल उदाहरण में। मैं नहीं चाहता कि जब प्रोग्राम निकल जाए तो कार्यपुस्तिका बंद हो जाएंगी।

समस्या यह है कि जब मेरा सी # प्रोग्राम निकलता है, समय के साथ, एक्सेल कार्यपुस्तिकाएं धीरे-धीरे अधिक स्मृति का उपभोग करती हैं, जब तक कि वे मूल 500 एमबी से 3.5 गीगा मेमोरी का उपभोग नहीं कर लेते।

मैं कार्यपुस्तिकाओं को हाथ से खोलता था, और चादरों ने कभी भी इतना स्मृति नहीं खाई। एक बार मैंने सी # का उपयोग करके उन्हें खोलना शुरू कर दिया, तो चरम स्मृति उपयोग के कारण वे तोड़ने लगे। मेरा सिद्धांत यह है कि किसी भी तरह, जब मैं COM Excel ऑब्जेक्ट से सहभागिता करता हूं, तो मैं एक स्मृति रिसाव बनाता हूं।

नीचे अपने मूल कोड है:

using Excel = Microsoft.Office.Interop.Excel; 
... 
excelApp = new Excel.Application(); 
excelApp.Visible = true; 
excelApp.Workbooks.Open(filename, misValue, misValue, misValue, misValue, misValue, 
       true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue); 
excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic; 

मैं के बारे में है कि कैसे आप का उपयोग करता है जारी करने के लिए मार्शल उपयोग करने की आवश्यकता को पढ़ने, तो मैं अब निम्नलिखित कोड अन्य कोशिश कर रहा हूँ, लेकिन यह परीक्षण करने के लिए कोई आसान तरीका है, सभी चादरें खोलने और देखने से कि वे बहुत अधिक डेटा का उपभोग करते हैं।

  excelApp = new Excel.Application(); 
      excelApp.Visible = true; 
      Excel.Workbooks currWorkbooks = excelApp.Workbooks; 
      Excel.Workbook currWorkbook = currWorkbooks.Open(filename, misValue, misValue, misValue, misValue, misValue, 
       true, misValue, misValue, misValue, misValue, misValue, misValue, misValue, misValue); 
      //excelApp.Calculation = Excel.XlCalculation.xlCalculationAutomatic; 

      int x = Marshal.ReleaseComObject(currWorkbook); 
      currWorkbook = null; 

      int y = Marshal.ReleaseComObject(currWorkbooks); 
      currWorkbooks = null; 
+0

आप पहले से ही currWorkbook को शून्य पर सेट कर चुके हैं .. तो आप इसे दो बार क्यों कर रहे हैं। Mashal.ReleaseComObject (currWorkBook) आपको बस इतना करना है कि आप यह जांचने के लिए एक इंट असाइन करने का प्रयास क्यों कर रहे हैं कि ऑब्जेक्ट जारी किया गया है या नहीं .. क्या आपको कोई त्रुटि मिल रही है .. – MethodMan

+0

मुझे कोई त्रुटि नहीं मिल रही है। समस्या यह है कि कार्यपुस्तिकाएं इस तरह से शुरू हुईं, धीरे-धीरे अधिक से अधिक स्मृति का उपभोग करें। – user804649

+0

आप EPPlus (http://epplus.codeplex.com/) को देखना चाहते हैं। मुझे यकीन नहीं है कि इसमें किस प्रकार का मैक्रो समर्थन है (यह एक फीचर के रूप में वीबीए का उल्लेख करता है), लेकिन आम तौर पर, मुझे एक्सेल इंटरऑप की तुलना में अधिक कुशल और कम परेशानी-प्रवण होने के लिए ईपीप्लस मिल गया है। – devuxer

उत्तर

16

जब एमएस ऑफ़िस COM इंटरॉप लाइब्रेरी का उपयोग कर, वहाँ मेमोरी लीक से बचने के लिए मैं का सामना करना पड़ा चीजों के एक जोड़े हैं:

सबसे पहले, "दो डॉट्स का उपयोग न करें" सबसे अच्छा है इसे याद रखने का तरीका, लेकिन मूल रूप से, हमेशा एक नए चर के लिए एक नया COM ऑब्जेक्ट संदर्भ असाइन करें, चेन-कॉल सदस्यों को न करें, भले ही इंटेलिसेंस इसे प्रोत्साहित करे।

//use vars for every COM object so references don't get leftover 
//main Excel app 
var excelApp = new Application(); 
var workbooks = excelApp.Workbooks; 

//workbook template 
var wbReport = workbooks.Add(@"C:\MyTemplate.xltx"); 

//Sheets objects for workbook 
var wSheetsReport = wbReport.Sheets; 
var wsReport = (Worksheet)wSheetsReport.get_Item("Sheet1"); 

दूसरे, के विपरीत क्रम में बनाई गई प्रत्येक चर के लिए Marshal.ReleaseComObject() कॉल करें: श्रृंखलित बुला पृष्ठभूमि जो .NET फ्रेमवर्क द्वारा उचित रिलीज होने से बचाता है में कुछ सामान करता है .. यहाँ कुछ कोड मैं एक एक्सेल रिपोर्ट प्रारंभ करने के लिए उपयोग है सृजन, और ऐसा करने से पहले कचरा संग्रहण के तरीकों की एक जोड़ी फोन:

//garbage collector 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

//cleanup 
Marshal.ReleaseComObject(wsReport); 
Marshal.ReleaseComObject(wSheetsReport); 
Marshal.ReleaseComObject(wbReport); 
Marshal.ReleaseComObject(workbooks); 
Marshal.ReleaseComObject(excelApp); 

इस योजना हर बार जब मैं का उपयोग एक्सेल मेरी स्मृति मुद्दों को हल किया है का उपयोग करना है, हालांकि यह कठिन और दुख की बात है कि हम श्रृंखलित सदस्यों उपयोग नहीं कर सकते है जिस तरह से हम उपयोग कर रहे हैं।

+4

अधिक जानकारी के लिए, यह महान प्रश्नोत्तर देखें: http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects। ध्यान दें कि बाद के कुछ उत्तर स्वीकृत उत्तर से बेहतर हो सकते हैं। – devuxer

+0

आह, यह वह जगह हो सकती है जहां मैंने आदतों को उठाया .. मुझे याद नहीं आया कि मैंने इसे कहाँ पढ़ा था, यह बहुत समय पहले था, इसलिए मैंने अभी जवाब दिया ... वह लिंक शायद पढ़ने के लिए सबसे अच्छी बात है। :) –

+0

+1 मैंने कई स्थानों पर पढ़ा था कि "दो बिंदु" का उपयोग करना अच्छा नहीं था, लेकिन मुझे नहीं पता था कि क्यों। अब मैं करता हूँ! –