C#DLL P / Invoke CallbackOnCollectedDelegate错误

时间:2011-04-11 08:54:09

标签: c# .net pinvoke invoke

 public delegate int MFS100_CodeLineDelegate(int code, int docId, string codeline);

 public event MFS100_CodeLineDelegate MFS100_CodeLine;

 MFS100_CodeLineDelegate OnCodeline = new MFS100_CodeLineDelegate(MFS100_OnCodeLine);
 AdressCodeLine = Marshal.GetFunctionPointerForDelegate(OnCodeline);
 mfSetEvent((int)EventEnum.E_EVENT_CODELINE, AdressCodeLine.ToInt32());

 object cl = (object)AdressCodeLine;
 GC.KeepAlive(cl);

 [DllImport("mflib.dll")]
 public static extern int mfSetEvent(int eventID, int callsback);

 *Global variable*
 private static IntPtr AdressCodeLine;

我将代理内存地址发送到dll以设置设备,当我从dll收到回调时,我得到错误:“检测到CallbackOnCollectedDelegate”。我该如何解决这个问题

2 个答案:

答案 0 :(得分:2)

GC.KeepAlive("your Delegate instance").

you could store your delegate instance on a global variable.

编辑1:

看下面的代码,你会弄明白我的意思

public class CallbackDemo
{
    //Don't forget to change the calling convention accordingly
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate int MFS100_CodeLineDelegate(int code, int docId, string codeline);
    public event MFS100_CodeLineDelegate MFS100_CodeLine;

    //this is one method how you keep your delegate instance being collected by GC
    private readonly MFS100_CodeLineDelegate cache;

    public CallbackDemo()
    {
        cache = OnCallBack;
    }
    protected virtual int OnCallBack(int code,int docId,string codeline)
    {
        if(this.MFS100_CodeLine!=null)
        {
            MFS100_CodeLine(code, docId, codeline);
        }
        return 0;
    }

    [DllImport("mflib.dll")]
    private static extern int mfSetEvent(int eventID, MFS100_CodeLineDelegate callsback);

    private MFS100_CodeLineDelegate myDelegate;
    public void CallSetEvent(int eventId)
    {
        mfSetEvent(eventId, this.cache);

    }

}

答案 1 :(得分:1)

你在错误的对象上调用KeepAlive--一个AddressCodeLine值的盒装副本。你想要保持活力的是委托对象本身,OnCodeline。

现在,KeepAlive只保留对象,直到方法返回。如果可以异步调用回调委托,则应该从字段引用委托。