简体   繁体   中英

C# DLL P/Invoke CallbackOnCollectedDelegate Error

 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;

I send the Delegate Memory Address to dll for set the device and when i get callback from dll i get Error: "CallbackOnCollectedDelegate was detected". How can i solve this problem

GC.KeepAlive("your Delegate instance").

or

you could store your delegate instance on a global variable.

EDIT 1:

look at the following code, you'll figure out what I meant

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);

    }

}

You're calling KeepAlive on the wrong object - a boxed copy of the AddressCodeLine value. What you want to keep alive is the delegate object itself, OnCodeline.

Now, KeepAlive only keeps the object alive until the method returns. If the callback delegate can be called asynchronously, you should reference the delegate from a field instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM