标签:start bre local isl 垃圾 alarm llb scom list
最近在写一个海康的门禁的自动监控刷卡事件的程序。
因为用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”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。
标签:start bre local isl 垃圾 alarm llb scom list
原文地址:https://www.cnblogs.com/KevinMO/p/11660708.html