public static List<RowColumnInfo> testGetCellList(excel.Application app, excel.Workbook wb)
{
excel.Sheets wss = wb.Worksheets;
excel.Worksheet ws = wss[1];
excel.Range regionRng = ws.UsedRange;
List<RowColumnInfo> list = ExcelUtils.GetCellList(regionRng);
excel.Range r2 = ws.UsedRange;
Console.WriteLine("释放uRng0");
MarshalUtils.ReleaseComObject(ref regionRng); // 返回0
MarshalUtils.ReleaseComObject(ref r2); // 返回0
Console.WriteLine("释放ws0");
MarshalUtils.ReleaseComObject(ref ws);
Console.WriteLine("释放wss0");
MarshalUtils.ReleaseComObject(ref wss); // 返回0
return list;
}其中MarshalUtils.ReleaseComObject 方法和Marshal.ReleaseComObject类似。似乎ws.UsedRange不需要释放,多次创建了其COM对象,但每次释放时,返回的RCW引用数都是0。
excel.Sheets对象似乎多次引用,也不会递增引用计数。
而excel.Worksheet如果多次引用不释放,则会递增引用计数。
确切的说,RCW对象可被GC回收,从而释放关联的COM对象。
不过我发现,我编写的一段代码中,从Range对象获取了Application对象,并从Application对象获取了CellFormat对象,如果不释放CellFormat对象,仅释放Application对象并不能及时释放RCW与COM对象。
excel.Application app = regionRng.Application; excel.CellFormat findFormat = app.FindFormat; findFormat.Clear(); MarshalUtils.ReleaseComObject(ref findFormat);
对于其他情况,即使我不显示释放任何Range,Worksheet,Sheets,仅释放Application对象,不会残留Excel进程。
由于GC的不确定性,它可能无法及时释放相关对象,会残存excel进程,如果需要实时性,可以手动释放所涉及的对象。
不过要非常小心谨慎。而且尽量不要使用链式的多个点的方式。如:
excel.CellFormat findFormat = regionRng.Application.FindFormat; findFormat.Clear(); MarshalUtils.ReleaseComObject(ref findFormat);
微软并不推荐使用Marshal.ReleaseComObject,原因是,由于COM对象在不同方法中进行调用,很可能会多调用了此方法,导致其他方法无法使用。某些COM对象是单例的,这种情形会很容易导致RCW断开,发生严重错误。