Occorre che venga rilasciata * each object * Excel integerp utilizzando Marshal.ReleaseComObject?

Modifica

Vedere anche Come posso pulire correttamente gli oggetti integerperi di Excel? . Recentemente mi sono imbattuto in questa domanda e ho fornito molta comprensione nel problema di come disporre correttamente gli oggetti COM. Assicuratevi di controllare oltre la prima risposta (contrassegnata) perché le altre risposte vanno al di là delle semplici "non utilizzare due punti" e "utilizzare ReleaseComObject per each object com".

Ho rivisto questa domanda in primo luogo perché ho capito che, nonostante sia stato molto accurato di registrare e disporre tutti i miei oggetti COM, le mie istanze di Excel ancora non erano state disposte correttamente. Si scopre che ci sono modi in cui gli oggetti COM possono essere creati completamente non evidenti (per esempio, è ansible perdere oggetti COM anche se non utilizzate mai due punti). Inoltre, anche se siete approfonditi, se il tuo progetto supera una determinata dimensione, la probabilità di mancare di un object COM si avvicina al 100%. E può essere molto difficile trovare quello che hai perso quando questo accade. Le risposte alla domanda sopra riportta forniscono alcune altre tecniche per assicurarsi che l'istanza di Excel sia definitivamente chiusa. Nel frattempo, ho fatto un piccolo aggiornamento (ma significativo) al mio ComObjectManager (in basso) per riflettere ciò che ho imparato dalla domanda legata in precedenza.

Domanda originale

Ho visto diversi esempi in cui Marshal.ReleaseComObject() viene utilizzato con gli oggetti Excel Interop (ovvero gli oggetti dello spazio dei nomi Microsoft.Office.Interop.Excel), ma l'ho visto in diversi gradi.

Mi chiedo se posso scappare qualcosa di simile:

 var application = new ApplicationClass(); try { // do work with application, workbooks, worksheets, cells, etc. } finally { Marashal.ReleaseComObject(application) } 

O se devo rilasciare each singolo object creato, come in questo metodo:

 public void CreateExcelWorkbookWithSingleSheet() { var application = new ApplicationClass(); var workbook = application.Workbooks.Add(_missing); var worksheets = workbook.Worksheets; for (var worksheetIndex = 1; worksheetIndex < worksheets.Count; worksheetIndex++) { var worksheet = (WorksheetClass)worksheets[worksheetIndex]; worksheet.Delete(); Marshal.ReleaseComObject(worksheet); } workbook.SaveAs( WorkbookPath, _missing, _missing, _missing, _missing, _missing, XlSaveAsAccessMode.xlExclusive, _missing, _missing, _missing, _missing, _missing); workbook.Close(true, _missing, _missing); application.Quit(); Marshal.ReleaseComObject(worksheets); Marshal.ReleaseComObject(workbook); Marshal.ReleaseComObject(application); } 

Quello che mi ha spinto a fare questa domanda è che, essendo il devoto di LINQ, sono veramente voglia di fare qualcosa di simile:

 var worksheetNames = worksheets.Cast<Worksheet>().Select(ws => ws.Name); 

… ma sono interessato a finire con perdite di memory o processi fantasma se non rilascio each object di lavoro ( ws ).

Qualsiasi intuizione su questo sarebbe apprezzato.

Aggiornare

Sulla base delle risposte finora, sembra che ho veramente bisogno di rilasciare each singolo object com creato. Ho preso l'opportunità di build una class ComObjectManager per rendere un po 'più facile affrontare questa mal di testa. Devi ricordare di utilizzare il metodo Get() each volta che installa un nuovo object com, ma se lo fai, prenderà cura di tutto il resto per te. Per favore, fai sapere se vedete dei problemi con esso (o modificare e lasciare un commento se è ansible). Ecco il codice:

 public class ComObjectManager : IDisposable { private Stack<object> _comObjects = new Stack<object>(); public TComObject Get<TComObject>(Func<TComObject> getter) { var comObject = getter(); _comObjects.Push(comObject); return comObject; } public void Dispose() { // these two lines of code will dispose of any unreferenced COM objects GC.Collect(); GC.WaitForPendingFinalizers(); while (_comObjects.Count > 0) Marshal.ReleaseComObject(_comObjects.Pop()); } } 

Ecco un esempio di utilizzo:

 public void CreateExcelWorkbookWithSingleSheet() { using (var com = new ComObjectManager()) { var application = com.Get<ApplicationClass>(() => new ApplicationClass()); var workbook = com.Get<Workbook>(() => application.Workbooks.Add(_missing)); var worksheets = com.Get<Sheets>(() => workbook.Worksheets); for (var worksheetIndex = 1; worksheetIndex < worksheets.Count; worksheetIndex++) { var worksheet = com.Get<WorksheetClass>(() => (WorksheetClass)worksheets[worksheetIndex]); worksheet.Delete(); } workbook.SaveAs( WorkbookPath, _missing, _missing, _missing, _missing, _missing, XlSaveAsAccessMode.xlExclusive, _missing, _missing, _missing, _missing, _missing); workbook.Close(true, _missing, _missing); application.Quit(); } } 

Solutions Collecting From Web of "Occorre che venga rilasciata * each object * Excel integerp utilizzando Marshal.ReleaseComObject?"