使 COM 对象保持活动状态以对长时间运行的任务进行排队

Keeping a COM object alive to queue longrunning tasks

据我了解,COM 对象只能在实例化它们的线程中使用。如果该线程终止,该对象将变得无效,您将无法再使用它。我尝试这样做时遇到的错误是 COM object that has been separated from its underlying RCW cannot be used. 我通常看到的处理此问题的建议只是为您想要 运行.

的每个任务重新初始化一个新的 COM 对象

问题是我正在使用的 COM 对象处理与另一个程序的通信,并且使用新的 COM 对象重新建立与该程序的相同实例的连接很棘手。我想要的操作 运行 冗长且需要用户的反馈,因此将所有操作包含在单个任务中并不是真正可行的 afaik。

我想做的是围绕该 COM 对象构建一个包装器,将对它的调用放入队列中,以供适当的线程调用,这将与 async/await 兼容,我想知道这是否可能。但是为了避免 XY 问题,我会问一些不同的问题:

在主线程之外保持 COM 对象正常运行的最优雅方法是什么,以便我可以继续将其用于多种用途?

COM object that has been separated from its underlying RCW cannot be used.

要保持​​ COM 对象存活,您需要在全局范围内声明相应的 RCW,因此当从堆中刷出 RCW 时不会声明引用计数器。此外,您还需要注意任何可能导致您遇到的问题的 Marshal.ReleaseComObject 调用。此方法用于显式控制从托管代码使用的 COM 对象的生命周期。您应该使用此方法及时释放持有资源引用的基础 COM 对象,或者当必须按特定顺序释放对象时。

例如,如果您处理 Outlook 等 Office 应用程序,它可能会检测到 cross-thread 调用并在这种情况下抛出异常。

最好的解决方案是创建一个可以从辅助线程调用的调度程序,并在主线程上对此类调用进行排队,以便与 COM 服务器进行通信。或者只是考虑提取所有需要的信息(不涉及 COM 对象的标量值),这些信息可以简单地从辅助线程中使用,然后以您需要的方式处理它。