代表的问题 [英] problem with delegate

查看:60
本文介绍了代表的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这样做是为了从C代码调用非托管函数。 pCallback是一个函数指针,因此在托管端是一个委托。

I've made this to call unmanaged function from C code. pCallback is a function pointer so on the managed side is a delegate.

[DllImport("MyDLL.dll")]

public static extern Result SetCallback(
            IntPtr handle,
            Delegate pCallback,
            CallbackType Type);

现在我要设置

    public delegate void pfnCallback(uint PromptID, ttsEventType evt, IntPtr lData);

    public Form1()
    {
        pfnCallback cb = new pfnCallback(cback);
        (...)
        Wrapper.SetCallback(handle, cb, IntPtr.Zero, CallBackType.DEFAULT);
        (...)
        }

它给了我一个错误,说 ...当将委托传递给非托管代码时,必须保持它们的生命...

It gives my an error saying "... when passing delegates to unmanaged code, they must be kept alive ... "

有人可以帮助我吗?

问候

推荐答案

您正在将委托类型声明与委托实例混淆。是的,您公开了您的委托人声明,这是错误的。只有Form1类使用它,它应该是私有的。在这里重要的是委托的实例,即您用新语句创建的实例。

You are confusing the delegate type declaration with the instance of the delegate. Yes, you made your delegate declaration public, that was wrong. Only the Form1 class uses it, it should be private. It is the instance of the delegate that matters here, the one you created with the new statement.

现在,您将实例存储在Form1的局部变量中构造函数。这会使实例上的引用保持几微秒。构造函数完成后,该引用将消失,垃圾收集器可以在此之后的任何时候收集委托实例。它看不到非托管代码保留了对它的引用,收集器只能发现托管代码所拥有的引用。

Right now, you are storing the instance in a local variable of the Form1 constructor. That keeps a reference on the instance for a few microseconds. As soon as the constructor completes, that reference is gone and the garbage collector can collect the delegate instance at any point after that. It cannot see that the unmanaged code keeps a reference to it, the collector can only discover references held by managed code.

当非托管代码调用回调时,一切都不会发生一个收集的委托实例,您会听到一声巨响。您必须更改代码,以便对实例进行托管引用。一种简单的方法是在Form1类中添加一个私有成员来存储实例。

Nothing good happens when the unmanaged code calls the callback on a collected delegate instance, you'll hear a loud kaboom. You must change your code so that there will be a managed reference to the instance. One easy way to do this is to add a private member to the Form1 class to store the instance.

即使这可能不够好,Form1对象也将是垃圾。以及将来某个时候收集的资料。它也收集委托对象。您还必须确保非托管代码在发生这种情况后不能使用回调。给定类的名称(Form1),在这种特定情况下不太可能发生。但是要防御代码并拨打电话,以重置表单的FormClosing事件处理程序中的回调。

Even that might not be good enough, the Form1 object will be garbage collected at some point in the future as well. Which collects the delegate object as well. You also must make sure that the unmanaged code cannot use the callback after that happens. Given the name of the class (Form1), that isn't that likely to happen in this specific case. But code defensively and make a call that resets the callback in the form's FormClosing event handler.

这篇关于代表的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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