c# – C/C++LI:防止非托管资源的托管包装上的垃圾收集

前端之家收集整理的这篇文章主要介绍了c# – C/C++LI:防止非托管资源的托管包装上的垃圾收集前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个C非管理类NativeDog需要从C#使用,所以我创建了一个包装类ManagedDog.
// unmanaged C++ class
class NativeDog
{
    NativeDog(...); // constructor
    ~NativeDog(); // destructor
    ...
}

// C++/CLI wrapper class
ref class ManagedDog
{
    NativeDog* innerObject; // unmanaged,but private,won't be seen from C#
    ManagedDog(...)
    {
        innerObject = new NativeDog(...);
        ...
    }

    ~ManagedDog() // destructor (like Dispose() in C#)
    {
        // free unmanaged resources
        if (innerObject)
            delete innerObject;
    }

    !ManagedDog() // finalizer (like Finalize() in C#,in case
    {             // the user forgets to dispose)
        ~ManagedDog(); // call destructor
    }
}

一切都很好,我使用这样的课程:

// in C++/CLI
// this function is called from C++ code
void MyLibrary::FeedDogNative(NativeDog* nativedog)
{
    ... // (***)
}
// this function is called from C#,passes on the dog to the native function
void MyLibrary::FeedDogManaged(ManagedDog^ dog)
{
    NativeDog* rawdog = dog->innerObject;
    MyLibrary::FeedDogNative(rawdog);
}

// C# client code
void MyFunc()
{
    ManagedDog dog = new ManagedDog(...);
    MyLibrary.FeedDogManaged(dog);
}

看看有什么问题?我一开始没有,直到很奇怪的事情不时发生.基本上,如果在调用MyFunc()之后,程序被GC暂停,而它位于本机函数FeedDogNative(上面标记(***))的某个位置,则会认为可以收集托管的包装器,因为它将不再被使用,没有在C#MyFunc(它是一个局部变量,不会在FeedDogManaged调用后使用),不在FeedDogManaged中.所以这实际上是发生在场合的. GC调用Finalizer,它会删除本机狗对象,即使FeedDogNative尚未完成使用!所以我的非托管代码现在使用一个已删除的指针.

我该如何防止这种情况?我可以想到一些方法(例如,在FeedDogManaged结束时假装使用狗的虚拟呼叫),但是推荐的方法是什么?

解决方法

您的FeedDogManaged功能需要一个 GC::KeepAlive()电话.似乎是一个确切的用例.
原文链接:https://www.f2er.com/csharp/94803.html

猜你在找的C#相关文章