【问题标题】:Defining a delegate as a function pointer将委托定义为函数指针
【发布时间】:2011-04-11 03:36:00
【问题描述】:

我正在使用一个调用非托管函数指针的委托。这会导致垃圾收集器在使用之前对其进行收集,如 MSDN 上的 CallbackOnCollectedDelegate MDA 页面中所述:MSDN page for CallbackOnCollectedDelegate MDA

决议规定我必须将适当的委托编组为非托管函数指针。我最初的反应是使用:

[MarshalAs(UnmanagedType.FunctionPtr)]
public delegate void EntityCallback([MarshalAs(UnmanagedType.SysInt)] IntPtr entity);

但是,C# 编译器不允许我编组委托,即使这是 MSDN 建议的解决方案。此外,MSDN 页面仅显示了引发问题的示例,但没有显示解决方案之一。

如何将我的委托编组为非托管函数指针或防止其被 GC?

编辑:按照建议,我创建了回调的引用。因此,我的代码从/更改为:

// From:
foo.SetCallback(new EntityCallback(bar));

// To:
call = new EntityCallback(bar); // Referenced in class
foo.SetCallback(call);

现在这确实有效 - 但仅限于调试模式。当我切换到 Release 时,它​​在同一点崩溃。这是为什么呢?

编辑2:更完整的代码sn-p:

public class Test
{
    private EntityCallback Call;

    private void Bar(System.IntPtr target)
    {
        ...
    }

    public Entity Foo { get; set; }

    public Test()
    {
        this.Foo = new Body.Sphere() { Visible = false }; // Irrelevant
        this.Foo.CollisionType = 3; // Irrelevant

        this.Call = new EntityCallback(this.Bar);

        this.Foo.SetCallback(this.Call, EntityCallbackType.Collision);
    }
}

【问题讨论】:

    标签: c# delegates unmanaged function-pointers


    【解决方案1】:

    您没有正确阅读。你必须这样做:

    ...更改您的代码以保留参考 给托管方的那个代表 在编组的一生中 非托管函数指针。

    换句话说,只需在您的类中存储对委托实例的引用,并确保类对象存在足够长的时间。如果确实需要,请使用静态。

    【讨论】:

    • 已编辑,请查看我的新问题。
    • 我无法从非常微薄的代码 sn-p 中判断存储“调用”的对象将存在多长时间。
    • 我仍然不知道是什么让 Test 对象保持活力。向类添加析构函数并记录一些内容,以便您知道它何时被收集。
    • 我确信 Test 没有被处理,因为 Test 负责程序的图形方面 - 如果它不存在,图形将不会更新。因此,可以安全地假设 Test 根本没有被丢弃。
    • 所以您收到了 MDA 警告,即使您 100% 确定实际上存在对委托的引用?谁错了,调试器还是你?如果您怀疑调试器,请关闭警告,Debug + Exceptions。
    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多