在后台线程中释放COM对象

kar*_*hul 2 c# com outlook

在C#中释放COM对象的扩展

我注意到保存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
Run Code Online (Sandbox Code Playgroud)

我写了几个测试,看起来像它的工作; 只是想知道这样做是否安全?"在不同于创建它的线程中释放COM对象"

谢谢

Karephul

Bre*_*McK 5

从非托管代码(C/C++)使用COM时,规则非常严格:您只能从获取对象的同一公寓中调用接口上的方法.因此,如果在STA线程上获得接口指针,则只允许该线程调用任何方法.如果在MTA线程上获得接口指针,则只有同一MTA中的其他线程才能使用该指针.穿过公寓的任何其他用途都要求将界面指针封送到另一个公寓.

然而,这是无人问世的世界..Net在COM上添加了一个完整的层,它掩盖了很多这些低级细节,而且大多数情况下,一旦你开始接触界面,你可以随心所欲地在线程之间传递该接口而不需要不得不担心旧的线程规则.这里发生的是它实际上传递了对称为"运行时可调用包装器"(RCW)的对象的引用,它正在管理底层的COM接口,并相应地控制对它的访问.(它承担了维护COM公寓规则的负担,因此您不必这样做,这也就是为什么旧的COM线程规则不适用于.Net:他们这样做,它们只是隐藏在您.)

所以你可以安全地从另一个线程调用Release或其他方法:但要注意,如果原始线程是STA,那么调用这些方法将导致底层RCW将调用编组回原始拥有线程,以便它仍然支持下层COM规则.因此,使用单独的线程最终可能无法让您获得任何性能!

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