对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段

Posted kevinmo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段相关的知识,希望对你有一定的参考价值。

最近在写一个海康的门禁的自动监控刷卡事件的程序。

因为用c#写的,大家都知道c#是垃圾自动回收的。海康提供的api是用c++写的,要将处理的回调代码委托给api 。刚开始的时候很顺利,但当运行一段时间就会报以下错误:

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 

大致的原因是:c#把回调函数资源回收了,导致api收到事件的时候执行回调出错。

网上的解决方案是将回调方法写成static的(静态方法)。但我这里不行。

最后还是微软官方的解决方法可靠: 

除了设置成static的还要在代码后加:GC.KeepAlive(dev);

 

 

        public static void MsgCallback(int lCommand, ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
        {
            try
            {
                switch (lCommand)
                {
                    case CHCNetSDK.COMM_ALARM_ACS:
                        ProcessCommAlarmACS(ref pAlarmer, pAlarmInfo, dwBufLen, pUser);
                        break;
                    default:
                        break;
                }
            }
            catch (System.Exception ex)
            {
                Program.WriteLog(0, "处理事件报错:" + ex);
            }


        }

  

        private void StartRead()
        {
            Program.LocalWriteLog("进入StartRead...........");
            zd.zd api = new zd.zd();
             for (int i = 0; i < _listDoors.Count; i++)
                {
                    Door d = _listDoors[i];
                    if (!d.isLogon)
                    {
                        CHCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO();
                        loginInfo.wPort = Convert.ToUInt16(d.cPort);
                        loginInfo.sDeviceAddress = d.cIP;
                        loginInfo.sUserName = d.cLoginUser;
                        loginInfo.sPassword = d.cLoginPassword;
                        try
                        {
                            switch (i)
                            {
                                case 0:
                                    this._arLoginDevices[i] = new Device00(loginInfo);
                                    break;
                                case 1:
                                    this._arLoginDevices[i] = new Device01(loginInfo);
                                    break;
                                case 2:
                                    this._arLoginDevices[i] = new Device02(loginInfo);
                                    break;
                                case 3:
                                    this._arLoginDevices[i] = new Device03(loginInfo);
                                    break;
                                case 4:
                                    this._arLoginDevices[i] = new Device04(loginInfo);
                                    break;
                                case 5:
                                    this._arLoginDevices[i] = new Device05(loginInfo);
                                    break;
                                case 6:
                                    this._arLoginDevices[i] = new Device06(loginInfo);
                                    break;
                                case 7:
                                    this._arLoginDevices[i] = new Device07(loginInfo);
                                    break;
                                case 8:
                                    this._arLoginDevices[i] = new Device08(loginInfo);
                                    break;
                                default:
                                    this._arLoginDevices[i] = new Device09(loginInfo);
                                    break;
                            }
                            
                            //this.listGch.Add(GCHandle.Alloc(this._arLoginDevices[i]));
                            Program.LocalWriteLog("加入设备:" + loginInfo.sDeviceAddress);
                        }
                        catch (System.Exception ex)
                        {
                            string cMsg = "加入设备出错:IP," + loginInfo.sDeviceAddress + ",信息:" + ex.Message;
                            Program.LocalWriteLog(cMsg);
                            api.AddLog(_key,0,cMsg);
                        }
                    }
                }
             int j=0;
             while (true)
             {
                 foreach (var dev in this._arLoginDevices)
                 {
                     if (dev == null)
                     {
                         continue;
                     }
                     if (!dev.IsLogin)
                     {
                         try
                         {
                             dev.Login();
                         }
                         catch (System.Exception ex)
                         {
                             string cMsg = "登录设备出错:IP," + dev.DeviceLoginInfo.sDeviceAddress + ",信息:" + ex.Message;
                             Program.LocalWriteLog(cMsg);
                             api.AddLog(_key, 0, cMsg);
                         }

                     }
                     if (dev.IsLogin && !dev.IsGuard)
                     {
                         try
                         {
                             dev.Guard();
                         }
                         catch (System.Exception ex)
                         {
                             string cMsg = "监控设备出错:IP," + dev.DeviceLoginInfo.sDeviceAddress + ",信息:" + ex.Message;
                             Program.LocalWriteLog(cMsg);
                             api.AddLog(_key, 0, cMsg);
                         }
                     }
                     GC.KeepAlive(dev);
                 }
                 System.Threading.Thread.Sleep(5 * 1000);
             }

             Program.LocalWriteLog("正常退出");
                
        }

  

 

以上是关于对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段的主要内容,如果未能解决你的问题,请参考以下文章

类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们的问题的解决方法

JAVA的事件委托机制和垃圾回收机制

垃圾回收机制

JVM基础-垃圾回收机制

Java开发中垃圾回收的最佳做法?

JAVA 中垃圾回收GC 的类型