簡體   English   中英

哪個Excel Interop對象可以清理自己以及通過GC.Collect()清理哪些對象

[英]Which Excel Interop objects to clean up myself and which to clean up by GC.Collect()

題:

我想問一個問題,以回應Mike Rosenblum這個問題 的回答 問題是關於清理Excel互操作對象。 建議的幾個解決方案(例如包裝器,不使用多個點,殺死excel過程),但我最喜歡Mike Rosenblum解決這個問題的方法( 關於該主題的冗長文章 )。

它基本上說的是你不要太擔心浮動的所有引用。 你只保留一些主要的(如ApplicationClassWorkbookWorksheet )。 您首先調用垃圾收集來清理浮動的所有對象,然后通過調用Marshal.FinalReleaseComObject (按重要性的相反順序)顯式清理您仍然擁有的主要引用。

現在我有兩個問題。
第一:如何確定我需要哪些對象來保持參考? Mike Rosenblum的例子中,他只保留了RangesWorksheetsWorkbooksApplicationClasses
第二:如果有更多的對象,我如何確定清理它們的順序(即“重要性順序”)?

提前致謝。


更新1:

MattC已經建議,對於訂單,唯一重要的是應用程序最后發布。 雖然在我的參考中使用了以下句子:“您還應該按重要性的相反順序發布命名引用:首先是范圍對象,然后是工作表,工作簿,最后是Excel應用程序對象。” 暗示有更多的排序。

nobugz建議將所有內容設置為null然后進行垃圾收集就足夠了,但這似乎與Mike Rosenblum的文章中的以下引用相矛盾:“那么你會認為你可以設置所有變量= Nothing然后調用GC.Collect()最后,這確實有效。但是,Microsoft Office應用程序對釋放對象的順序很敏感,不幸的是,設置變量= Nothing然后調用GC.Collect()並不保證發布對象的順序。“

更新2:

一些額外的信息:在我自己的應用程序中,我用圖表做了很多事情。 我正在設置很多屬性等。據我所知,有很多地方可以創建新的COM對象。 我試圖確保我從不使用雙點,我試圖在我完成的所有對象上調用Marshal.FinalReleaseComObject 我沒有使用包裝器方法,因為它會引入很多嵌套。
我的應用程序完成其工作后, EXCEL.exe沒有關閉。 但是......當我告訴我的應用程序再次執行相同的工作時,它確實關閉了。 當然打開了一個沒有關閉的新EXCEL.exe 現在我已經刪除了Marshal.FinalReleaseComObject調用的alllll,並且應用程序完全相同。 EXCEL.exe保持不變,直到我告訴我的應用程序重做工作,然后一個新的EXCEL.exe啟動並停留。

編輯:當我告訴我的應用程序做其他非COM相關的工作,一段時間后EXCEL.exe消失,但現在沒有出現新的EXCEL.exe

不確定我可以從中得出什么結論......

您應該可以在代碼中找到可能的實時引用,它們將是您的類中的字段。 或者清理方法中的局部變量,這是不太可能的。 鏈接中提供的列表只是您最有可能存儲在字段中的對象。 可能還有其他人,他們會保持Excel和Application對象一樣活着。

我不認為我會推薦鏈接中提倡的手提鑽方法,它只是隱藏了一個包含死COM接口的RCW的潛在生命參考。 最好的是你可能會永久性地泄漏到RCW對象,最壞的情況是當程序意外引用該對象時會導致程序崩潰。 可以肯定的是,Bugz不是你很容易發現的。 您所要做的就是將引用設置為null,順序無關緊要,然后收集。

我有一個類似的問題,這是我的抓住,最后看起來像清理。 我希望它有所幫助。

        .......

        oWB._SaveAs(strCurrentDir +
           strFile, XlFileFormat.xlWorkbookNormal, null, null, false, false,       XlSaveAsAccessMode.xlShared, false, false, null, null);
            sumsheet.Activate();
            oWB.Close(null, null, null);
            oXL.Workbooks.Close();
            oXL.Quit();
        }
        catch (Exception theException)
        {
            theException.ToString();
        }
        #region COM Object Cleanup
        finally
        {
            // Cleanup
            GC.Collect();
            GC.WaitForPendingFinalizers();

            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oRng);
            //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sumSheet);
            //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oSheet);
            //oWB.Close(null, null, null);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oWB);
            oXL.Quit();
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oXL);
        }
        #endregion

編輯

如果您注意到我已經注釋掉sumSheet + oSheet(這是我的工作表),因為它不需要。 這段代碼對我來說沒有任何問題。 我通過重新排列順序找到了錯誤。

我認為只要應用程序是最后一個,您可以按任何順序釋放它們(只要它們不為空)。

然后執行GC.Collect以最終終止excel.exe進程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM