释放临时COM对象
使用COM对象考虑以下C#代码。
MyComObject o = new MyComObject; try { var baz = o.Foo.Bar.Baz; try { // do something with baz } finally { Marshal.ReleaseComObject(baz); } } finally { Marshal.ReleaseComObject(o); }
这将释放COM对象o
和baz
,但不释放由o.Foo
和o.Foo.Bar
的临时对象。 当这些对象拥有大量非托管内存或其他资源时,这可能会导致问题。
一个明显但丑陋的解决方案是,使用try-finally
和Marshal.ReleaseComObject
使代码更加混乱。 请参阅C#+ COM Interop,确定性版本
作为一种解决方法,我创建了一个帮助类
class TemporaryComObjects: IDisposable { public C T(C comObject) { m_objects.Add(comObject); return comObject; } public void Dispose() { foreach (object o in m_objects) Marshal.ReleaseComObject(o); } }
class TemporaryComObjects: IDisposable { public C T(C comObject) { m_objects.Add(comObject); return comObject; } public void Dispose() { foreach (object o in m_objects) Marshal.ReleaseComObject(o); } }
用法:
using (TemporaryComObjects t = new TemporaryComObjects()) { MyComObject o = tT(new MyComObject); var baz = tT(tT(tT(o.Foo).Bar).Baz); // do something with baz }
using (TemporaryComObjects t = new TemporaryComObjects()) { MyComObject o = tT(new MyComObject); var baz = tT(tT(tT(o.Foo).Bar).Baz); // do something with baz }
我的问题:此代码是否存在潜在问题? 有人有更优雅的解决方案吗?
我最大的抱怨是免费精选名字大全, T
; Add
可能更具说明性。 我还将where T : class
添加到generics方法中,但“流畅的API”似乎可用。 我也倾向于将代码扁平化。 我还可以看到一些使用Expression
API来遍历整个树并捕获所有中间步骤的方法,但这不是一件容易的事 – 但想象一下:
using(var com = new SomeWrapper()) { var baz = com.Add(() => new MyComObject().Foo.Bar.Baz); }
这是一个表达式树,我们自动获得中介。
(另外,你可以在Dispose()
Clear()
或Clear()
列表)
像这样:
static class ComExample { static void Main() { using (var wrapper = new ReleaseWrapper()) { var baz = wrapper.Add( () => new Foo().Bar.Baz); Console.WriteLine(baz.Name); } } } class ReleaseWrapper : IDisposable { List
Marc Gravell的解决方案不适用于.Net 4. +,因为在COM而不是对象中引入了Dynamic。 此外,在使用Excel COM进行测试时,构造函数会出现“转换不支持”(WalkImpl开关的默认值)的exception。
Expressions还有其他限制,因为没有索引属性,也没有可选参数。 从来没有编码表达式之前我不知道如何解决这些问题。
不会编译或执行:
上述就是C#学习教程:释放临时COM对象分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
using (var wrapper = new ComWrapper()) { var application = wrapper.Add(() => new Excel.Application()); var workbook = wrapper.Add(() => application.Workbooks.Open(@"C:MyExcel.xls")); Excel.Range range = wrapper.Add(() => workbook.Sheets[1].UsedRange); string value = wrapper.Add(() => range.Cells[1, 1]).Value2; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/942579.html