- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
编辑
另请参阅 How do I properly clean up Excel interop objects? .我最近遇到了这个问题,它提供了很多关于如何正确处理 COM 对象的问题的见解。一定要检查第一个(标记的)答案,因为其他答案超出了简单的“不要使用两个点”和“对每个 com 对象使用 ReleaseComObject
”的建议。
我首先重新审视了这个问题,因为我意识到,尽管我对所有 COM 对象的注册和处置都非常彻底,但我的 Excel 实例仍然没有得到正确处置。事实证明,有一些方法可以创建完全不明显的 COM 对象(即,即使您从不使用两个点,也可能会错过 COM 对象)。此外,即使你很彻底,如果你的项目增长超过一定规模,那么遗漏 COM 对象的可能性接近 100%。当发生这种情况时,很难找到您错过的那个。上面链接的问题的答案提供了一些其他技术来确保 Excel 实例确实关闭。同时,我对我的 ComObjectManager
(如下)做了一个小的(但重要的)更新,以反射(reflect)我从上面链接的问题中学到的东西。
原始问题
我见过几个例子,其中 Marshal.ReleaseComObject()
与 Excel Interop 对象(即来自命名空间 Microsoft.Office.Interop.Excel 的对象)一起使用,但我见过它使用在不同程度上。
我想知道我是否可以摆脱这样的事情:
var application = new ApplicationClass();
try
{
// do work with application, workbooks, worksheets, cells, etc.
}
finally
{
Marashal.ReleaseComObject(application)
}
或者如果我需要释放创建的每个对象,就像在这个方法中:
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);
}
促使我问这个问题的是,作为 LINQ 的忠实拥护者,我真的很想做这样的事情:
var worksheetNames = worksheets.Cast<Worksheet>().Select(ws => ws.Name);
...但我担心如果我不释放每个工作表 (ws
) 对象,我最终会遇到内存泄漏或幽灵进程。
如有任何见解,我们将不胜感激。
更新
根据目前的答案,听起来我确实需要释放我创建的每一个 com 对象。我借此机会构建了一个 ComObjectManager
类,以便更轻松地处理这个令人头疼的问题。每次实例化一个新的 com 对象时,您都必须记住使用 Get()
方法,但如果您这样做,它将为您处理其他所有事情。如果您发现任何问题,请告诉我(如果可以,请编辑并发表评论)。这是代码:
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());
}
}
这是一个用法示例:
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();
}
}
最佳答案
我相信您必须对每个 COM 对象调用 ReleaseComObject。由于它们未被垃圾回收,因此父子层次结构并未真正纳入等式:即使您释放父对象,它也不会减少任何子对象的引用计数。
关于c# - 是否需要使用 Marshal.ReleaseComObject 释放*每个* Excel 互操作对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2926205/
在编程环境中是哪一个?有区别吗?我已经看到了这两种方式,我不想在我的代码中拼错它。 最佳答案 编码(marshal)是工作图 block ;例如,消防编码(marshal)或美国编码(marshal)
我有以下结构: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WAVEHDR { in
我找不到以下问题的明确答案:如果一个 COM 类是线程安全的,即它被标记为 Both 或 Free,我真的需要编码它的对象接口(interface)以将它传递给另一个线程吗?相同的过程?我不问两个线程
在编译 C# ASP.NET 应用程序时,我从 Visual Studio 2008 中收到奇怪的警告。谁能告诉我这个警告的含义(如果可能的话,用几个音节的词)? At least one of th
TL;DR:MongoDB 驱动程序是否提供了编码和解码文档单个字段的功能? 这是一个非常简单的问题,但这里有一些上下文: 我有一个工作人员负责在 2 个独立的数据库之间同步数据。当它接收到事件消息时
是否可以在使用自定义编码(marshal)拆收器的结构上使用 Marshal.SizeOf()? 例如: struct Abcde { public int test1; [MarshalAs
我有一张 map :[]map[string]string . 将结果填充到 json.marshal()兼容的对象。输出: [ { "key1": "val1", "key2":
如何在没有根元素的情况下进行编码(marshal)? type Ids struct { Id []string `xml:"id"` } IdsStr, _ := xml.Marshal(&Id
我有这个 C++ 代码: extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo) { *foo =
我创建了 map[string]interface{} 并且我想通过 2 个重置服务之间的映射传递多种类型。 每次我编码时,我都会在应该包含 reflect.Type 的字段中得到空映射。 Servi
我有一个托管的 .Net 类,它创建了我需要确保正确清理的非托管资源。 我有一个顺序结构: [StructLayout(LayoutKind.Sequential)] struct FooBar {
我在用 val akkaV = "2.2.3" val sprayV = "1.2.0" Seq( "io.spray" % "spray-can" % spra
我正在使用 Castor 编码/取消编码我的 Java 对象,其中一个对象包含一个 EnumMap。Castor 可以编码(marshal)/解封 EnumMaps 吗?我有一个带有一些嵌套 Hash
错误:com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:无法编码类型类 [Ljava.lang.Strin
我们在 netbeans 中做了一次 cleanbuild,检查了 jdk 版本并在服务器上部署了所有内容,但仍然出现以下错误。有人可以帮忙吗? javax.servlet.ServletExcept
我想知道是否可以对我的类进行注释,以便编码器第一次遇到对象时,它会生成适当类型的 XML 元素,但任何其他对该对象的后续引用都将具有 XML IDREF条目已创建? 最佳答案 您可以利用 JAXB 的
我正在从现有代码构建一个通用类库,但我收到了一些编译器警告,提示我终其一生都不知道该如何处理。 我有这样的代码: void SomeMethod(Object data) { var size =
我在编码我的 JAXBElement 时遇到了这个异常,它有几个子元素。我如何弄清楚如何查明导致此异常的子元素? java.lang.NullPointerException at com.s
本文整理了Java中org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller.marshall()方法的一些代码示例,展示
我最近已经问了一个有关 JAXB 的问题,可以在以下位置找到:How to marshal/unmarshal Java objects with private fields using JAXB
我是一名优秀的程序员,十分优秀!