c# - 在后台线程中释放 COM 对象

标签 c# com outlook

扩展到 Release COM Object in C#

我注意到保存和释放 MailItem 是一项耗时的任务。那么,执行以下操作是否安全? (下面的伪代码)

Thread 1 (main thread)
- Open 10 (different .msg files) - MailItems [List<MailItem> items]
- user works on them and want to save and close all of them with one click.

- On_save_All_click (runs on main thread)
- Do
- toBeClearedList.addAll(items);
- items.clear() [so that main thread cannot access those items]
- BG_Thread.ExecuteAsyn(toBeClearedList);
- End

Thread 2 (background thread) (input - List<MailItems>) 
- foreach(MailItem item in input)
    item.save();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(item)
- done

我写了几个测试,看起来很有效;只是想知道这样做是否安全? “在与创建它的线程不同的线程中释放 COM 对象”

谢谢

卡勒普尔

最佳答案

从非托管代码 (C/C++) 使用 COM 时,规则非常严格:您只能从获取对象的同一单元调用接口(interface)上的方法。因此,如果您获得 STA 线程上的接口(interface)指针,则只允许该线程调用任何方法。如果您获得 MTA 线程上的接口(interface)指针,则只有同一 MTA 中的其他线程可以使用该指针。任何其他跨单元的使用都需要将接口(interface)指针编码到其他单元。

然而,那是未受破坏的世界。 .Net 在 COM 之上添加了一个完整的层,其中隐藏了许多这些低级细节,并且在大多数情况下,一旦您掌握了接口(interface),就可以在线程之间尽可能多地传递该接口(interface),而无需不必担心旧的线程规则。这里发生的事情是,它实际上传递对一个称为“运行时可调用包装器”(RCW) 的对象的引用,并且它正在管理底层 COM 接口(interface),并相应地控制对其的访问。 (它承担了维护 COM 单元规则的负担,因此您不必这样做,这就是为什么旧的 COM 线程规则似乎不适用于 .Net 的原因:它们适用,它们只是隐藏在你。)

因此您可以从另一个线程安全地调用 Release 或其他方法:但请注意,如果原始线程是 STA,则调用这些方法将导致底层 RCW 将调用编码回原始拥有线程,以便它仍然维护底层 COM 规则。因此,使用单独的线程最终可能不会真正让您获得任何性能!

一些值得阅读的文章在这里填写了一些细节:

关于c# - 在后台线程中释放 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9282455/

相关文章:

c# - 为什么从 C# 启动时从 VB 调用 C# COM 对象会出现 0x80070002 错误?

c++ - 当我尝试使用 CComObject 函数创建实例时,_pAtlModule 指针为空

c# - 如何将 C# 动态变量属性分配给另一个动态对象?

c# - 匹配源ElasticSearch Nest中的每个字段

c# - 如何在组合框中添加 2 列?

c# - 包装 C# lambda 表达式

html - 在图像右侧居中放置两行文本

outlook - 如何使用 ical.net 创建 HTML 格式的 ICS 消息正文?

vba - 禁止显示程序正在尝试访问我的邮件的对话框警告

c# - ASP.Net MVC - Swashbuckle 无法识别任何 Controller