Invoke类型的已垃圾回收委托进行了回调

C#调用C++的函数出现了这个异常,记录之。

 public delegate void VOIPREGSTATEPROC(IntPtr hReg, VOIPREG_STATE state, IntPtr msg);
    public delegate void VOIPCALLSTATEPROC(IntPtr hCall, VOIPCALL_STATE state, IntPtr msg);
    public delegate void VOIPAUTHREQPROC(IntPtr hAuth, VOIPAUTH_METHOD method);
    public struct VOIPINITSTRUCT
    {
        public VOIPREGSTATEPROC pfnRegStateChange;   // SIP注册状态回调
        public VOIPCALLSTATEPROC pfnCallStateChange; // 通话状态回调
        public VOIPAUTHREQPROC pfnAuthRequested;     // 认证回调
        public IntPtr pszRingFileDirPath;       // 默认铃声目录路径(目录下需要有ring.wav和ringback.wav两个文件)
        public IntPtr pszLicense;               //授权码 6b240c1094a86518738c4bc76a22f609
    }


 [DllImport("./Voip/VoipDLL/MyVoIp.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
        public static extern int MVoipInitialize(IntPtr pvis);

起初的用法,是在程序窗体的load事件中初始化了一个局部结构体。

VOIPINITSTRUCT m_vis;
m_vis.pfnRegStateChange = VoipRegStateProc;
m_vis.pfnCallStateChange = VoipCallStateProc;
m_vis.pfnAuthRequested = VoipAuthReqProc;
m_vis.pszRingFileDirPath = IntPtr.Zero;
m_vis.pszLicense = IntPtr.Zero;
IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(m_vis));
Marshal.StructureToPtr<VOIPINITSTRUCT>(m_vis, intPtr, false);
VoIP.MVoipInitialize(intPtr);

这样使用,过一段时间就会出现“Invoke类型的已垃圾回收委托进行了回调”异常。

查阅了一下。

关于GC(.NET的垃圾回收)

分配在栈中的空间变量,一旦出了该变量的作用域就会被CLR立即回收;

C# 中的结构体是值类型,分配在栈中。如我上述用法,在窗体load方法执行结束,结构体分配的内存空间就被垃圾回收了,也就导致了异常了。

我的解决方案就是定义一个全局的静态变量(public static VOIPINITSTRUCT m_vis;)。如此,结构体分配的内存空间直到程序退出才会释放内存。

猜你喜欢

转载自blog.csdn.net/ezreal_pan/article/details/86573520