How to clean up COM references in .NET when app will be left running?

我与影子孤独终老i 提交于 2019-12-05 23:55:02

In general, when working with the Office PIAs, i've found that these sorts of problems with objects not being released arise when you have instance variables that hold COM objects. In your case, these would be xlsApp and xlsWb. You don't have to quit the Excel application in order to release the objects, but you do have to perform the following as a cleanup procedure:

Marshal.FinalReleaseComObject(xlsWb);
xlsWb = null;

Marshal.FinalReleaseComObject(xlsApp);
xlsApp = null;

GC.Collect();

Local-scoped variables containing COM objects don't seem to cause this problem, only instance variables. I hope this helps!

I'm a tad confused - at the end of RunMeFirst you exit the process, so is RunMeSecond run in a different process from the first method or the same process?

Either way I would change your code so that xlsWb is scoped locally and just do the following:

public void RunMeFirst()
{
    System.Type oSEType = Type.GetTypeFromProgID("Excel.Application");
    xlsApp = Activator.CreateInstance(oSEType);
    Workbook xlsWb = xlsApp.Workbooks.Open("C:\\test1.xls");

    // Do stuff
    xlsWb.Close(false);

    System.Environment.Exit(0);
}

You shouldn't really call any of the ReleaseComObject methods except in certain circumstances (for example in server applications where many COM objects will all be in use and so it is critical to release objects as soon as possible). The usual mechanism for cleaning up COM object should simply be to let them go out of scope, in which case the COM object will be released using the same magic the GC uses (I believe that it is cleaned up as the finalizer is run, but I'm not 100% sure on this).

The reason why its a good idea to scope xlsWb locally (rather than as a class member or a static member) is that class members will only be cleaned up when the class is cleaned up, and static members are never cleaned up until the appdomain is unloaded. If you do need to clean up a COM object referenced by a static field then the way to do this is to set the static field to null so the underlying COM object can be cleaned up by the GC scoping rules:

xlsWb = null;

Also there should be no real need to call GC.Collect for similar reasons - Mike Rosenblum gives a fair explanation as to why he's calling GC.Collect and ReleaseComObject, but no real justification as to why he isn't just satisfied with letting the garbage collector do its job. Like I said, there are situations where you might want more control over the release of COM objects, however these are the exception not the rule.

You may also find reading Marshal.ReleaseComObject Considered Dangerous useful.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!