如何在Release()上处理NET COM互操作对象 [英] How to dispose of a NET COM interop object on Release()

查看:124
本文介绍了如何在Release()上处理NET COM互操作对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用托管代码(C ++ / CLI)编写的COM对象。我在标准C ++中使用该对象。

当COM对象被释放时,如何强制我的COM对象的析构函数被立即调用?

I have a COM object written in managed code (C++/CLI). I am using that object in standard C++.
How do I force my COM object's destructor to be called immediately when the COM object is released? If that's not possible, call I have Release() call a MyDispose() method on my COM object?

我的代码声明对象(C ++ / CLI):

My code to declare the object (C++/CLI):


    [Guid("57ED5388-blahblah")]
    [InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface class IFoo
    {
        void Doit();
    };

    [Guid("417E5293-blahblah")]
    [ClassInterface(ClassInterfaceType::None)]
    [ComVisible(true)]
    public ref class Foo : IFoo
    {
    public:
    	void MyDispose();
    	~Foo() {MyDispose();} // This is never called
    	!Foo() {MyDispose();} // This is called by the garbage collector.
    	virtual ULONG Release() {MyDispose();} // This is never called
    	virtual void Doit();
    };

使用对象(本机C ++)的代码:

My code to use the object (native C++):


#import "..\\Debug\\Foo.tlb"
...
Bar::IFoo setup(__uuidof(Bar::Foo)); // This object comes from the .tlb.
setup.Doit();
setup->Release(); // explicit release, not really necessary since Bar::IFoo's destructor will call Release().

如果我在我的COM对象上放置一个析构函数,它不会被调用。如果我放一个finalizer方法,它会在垃圾收集器绕过它时被调用。如果我明确调用我的Release()覆盖它从未被调用。

If I put a destructor method on my COM object, it is never called. If I put a finalizer method, it is called when the garbage collector gets around to it. If I explicitly call my Release() override it is never called.

我真的很喜欢它,所以当我的本地Bar :: IFoo对象超出范围,调用我的.NET对象的dispose代码。我想我可以通过覆盖Release(),如果对象计数= 0,然后调用MyDispose()。但显然我不是正确地覆盖Release()正确,因为我的Release()方法从未被调用。

I would really like it so that when my native Bar::IFoo object goes out of scope it automatically calls my .NET object's dispose code. I would think I could do it by overriding the Release(), and if the object count = 0 then call MyDispose(). But apparently I'm not overriding Release() correctly because my Release() method is never called.

显然,我可以让我的MyDispose在接口中,并且要求使用我的对象的人在Release()之前调用MyDispose(),但是如果Release()刚刚清理了对象,它将是slicker。

Obviously, I can make this happen by putting my MyDispose() method in the interface and requiring the people using my object to call MyDispose() before Release(), but it would be slicker if Release() just cleaned up the object.

是否可以强制.NET COM对象的析构函数或一些其他方法,当COM对象被释放时立即被调用?

Is it possible to force the .NET COM object's destructor, or some other method, to be called immediately when a COM object is released?

在这个问题上搜索得到一个很多命中告诉我调用System.Runtime.InteropServices.Marshal.ReleaseComObject(),但当然,这是如何告诉.NET释放一个COM对象。我想要COM Release()处置一个.NET对象。

Googling on this issue gets me a lot of hits telling me to call System.Runtime.InteropServices.Marshal.ReleaseComObject(), but of course, that's how you tell .NET to release a COM object. I want COM Release() to Dispose of a .NET object.

推荐答案

实际上没有Dispose )而不是当最后一个引用被释放时,将从COM客户端调用Release。它只是没有实现。这里有一些想法如何这样的事情可以做到。

Actually neither the Dispose (or should i say ~Foo) not the Release will be called from the COM client when the last reference is released. It simply is not implemented. Here is some idea how such a thing could be done.

http://blogs.msdn.com/oldnewthing/archive/2007/04/24/2252261.aspx#2269675

但方法是即使作者也不建议。

But the method is not advised even by author.

如果实现COM客户端,最好的选择是查询IDisposable并显式调用Dispose,请求的iid是:

If you implement the COM Client as well the best option would be to query for IDisposable and call Dispose explicitly, iid to request is:

{805D7A98-D4AF-3F0F-967F-E5CF45312D2C}


b $ b

我可以想到的其他选项是实现某种自己的COM垃圾收集器。由COM创建的每个对象将被放置在一个列表中(假设您的类型的对象只能由COM创建 - 我不能想到任何方法来区分对象的创建位置)。然后你必须定期检查列表,并在每个对象调用如下:

Other option I can think of is to implement some sort of own "COM Garbage Collector". Each object created by COM would be placed in a list (Provided that objects of your type are only creatable by COM - I cannot think of any method to distinguish from where the object is created). And then you would have to periodically check the list, and on each object call something like this:

IntPtr iUnk = Marshal.GetIUnknownForObject(@object);
int refCount = Marshal.Release(iUnk);
if (refCount == 0)
    @object.Dispose();

但这是一个疯狂的想法。

but this is some crazy idea.

这篇关于如何在Release()上处理NET COM互操作对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆