COM 对象是否已与其 RCW 分离?
我正在尝试解决“无法使用已与其底层 RCW 分离的 COM 对象”错误的问题,我认为导致该问题的原因是 COM 对象在未实例化它们的线程上使用。
我不允许进行太多重构,并且由于对象应该在多个线程上可用,我想知道是否有一种方法可以在对它们进行可能导致上述错误的操作之前查明它们是否已在当前线程上创建。如果还没有,就创建它们。
另外,我对互操作这件事很陌生,所以如果有人愿意帮助我理解,我将非常感激:
线程完成后 COM 对象会发生什么,以及为什么 RCW 在另一个上仍然可用线程,即使它不再有 COM 对象(为什么它不为空?)。另外,为什么它会导致该错误并同时在 Marshal.IsCOMObject 上返回 true ?
在以下使用引用计数、包装器和内存的场景中会发生什么:
- 在线程 A 上创建 COM 对象 x
- 将其传递并保存在线程 B 上
- 创建另一个 x (或者,如果它是 y 会发生什么? ) 在线程 C 上
- 传递它并在线程 B 上覆盖 x
I'm trying to fix problem with "COM object that has been separated from its underlying RCW cannot be used" error, and I think what's causing it is that COM objects are used on a thread that didn't instantiate them.
I'm not allowed to do much refactoring, and since objects should be available on multiple threads I wonder if there is a way to find out if they have been created on current thread before doing something with them that would cause aforementioned error. And, if they haven't, create them.
Also, I'm new to this interop thing, so if someone would be kind enough to help me understand, I'd much appreciate it:
What happens with the COM object once the thread finishes, and why is RCW still available on the other thread even when it doesn't have the COM object in it anymore (why isn't it null?). Also, why would it cause that error and in the same time return true on Marshal.IsCOMObject?
What happens in the following scenario(s) with reference count and the wrapper and the memory:
- Create COM object x on the thread A
- Pass it and save it on the thread B
- Create another x (alternatively, what would happen if it were y?) on the thread C
- Pass it and overwrite x on the thread B
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
COM 对象会被 COM 自动销毁。当另一个线程继续使用它时,将产生“COM 对象已分离”异常消息。您不能允许线程退出。
显然,您有一个单线程 COM 服务器,这是迄今为止最常见的类型。它与创建它的 STA 线程具有亲和力。 COM 确保自动将另一个线程上进行的任何调用封送到创建该对象的线程。当线程消失后,它就不再起作用了。另请注意,您不会获得任何并发性。
获得此异常的另一种方法是错误地使用 Marshal.ReleaseComObject() 显式处理引用计数。也不是不可能,因为您应该收到 MDA 警告。
The COM object gets destroyed automatically by COM. Which will produce the 'COM object that has been separated' exception message when another thread continues to use it. You cannot allow the thread to exit.
Clearly you have an single threaded COM server, by far the most common kind. It has affinity to the STA thread on which it was created. COM makes sure to automatically marshal any calls made on another thread to the thread that created the object. That can no longer work when the thread is gone. Also beware that you don't get any concurrency.
Another way to get this exception is by making the mistake of handling reference counts explicitly with Marshal.ReleaseComObject(). Not unlikely either since you should have gotten an MDA warning.