工程中实际问题解决两例——基于C#
工程中实际问题解决两例——基于C#
1. try catch的妙用
1.1 遇到问题的现象
机房动环监控系统,添加了100多个站点,新加设备无法同步,界面点同步,通信服务会报错退出
同步设备操作如下:
通信异常如下:
大概意思是字典缓存中查无此值(根据键找)。
1.2 原因分析
其实每个比较大的bug都是系统设计不合理的地方,同时也是下次系统设计的宝贵经验。
同时需要阐明的是bug只要能复现,就一定能解决,或者是从正面解决,或者是策略解决(受限于资源或者网络的时候)。
主要从日志(文件打印或者命令窗口打印),数据库,代码三个层面。
1.2.1 先从数据库入手
找到数据库中历史数据插入的表deviceData,会不会因为有些字段为非空了,导致插入失败。全字段允许为空,结果依然报错;
1.2.2 代码日志逐级打印结合数据库
根据窗体报错的行数970,598,以及数据库中的PesudoDevice表,结合系统设计的逻辑,大体流程如下:请求设备上报数据,根据协议设备将上报数据格式(配置规则),平台将协议模板序列化保存到PesudoDevice表的content字段中。采集的数据会按照告警规则与信号点规则,保存到businessSignal与activeAlarm表中去。
其中主要的两个类型如下:
某机房的所有业务设备
/// <summary>
/// 业务设备模板内容
/// </summary>
public class PseudoDeviceTemplateContext
{
/// <summary>
/// 物理设备
/// </summary>
public List<string> ConcreteDeviceIDs { get; set; }
/// <summary>
/// 测点列表
/// </summary>
public List<PseudoDeviceTemplateSignal> Signals { get; set; }
}
单个信号点的类型
/// <summary>
/// 业务设备模板测点定义
/// </summary>
public class PseudoDeviceTemplateSignal
{
/// <summary>
/// 物理设备ID
/// </summary>
public string ConcreteDeviceID{get;set;}
/// <summary>
/// 物理设备名称
/// </summary>
public string ConcreteDeviceName{get;set;}
/// <summary>
/// 物理设备类型ID
/// </summary>
public string ConcreteDeviceTypeID {get;set;}
/// <summary>
/// 物理设备类型ID
/// </summary>
public string ConcreteDeviceTypeName { get; set; }
/// <summary>
/// 测点ID
/// </summary>
public string SignalID { get; set; }
/// <summary>
/// 通道ID
/// </summary>
public string ChannelID { get; set; }
/// <summary>
/// 通道名称
/// </summary>
public string ChannelName {get;set;}
/// <summary>
/// 通道类型
/// </summary>
public int? ChannelType {get;set;}
/// <summary>
/// 测点名称
/// </summary>
public string SignalName{get;set;}
/// <summary>
/// 测点类型ID
/// </summary>
public string SignalTypeID{get;set;}
/// <summary>
/// 单位ID
/// </summary>
public string UnitMeasureID { get; set; }
/// <summary>
/// 告警条件列表
/// </summary>
public List<SignalAlarmCondition> AlarmConditions { get; set; }
/// <summary>
/// 存储条件列表
/// </summary>
public List<DeviceDataStoreRule> DeviceDataStoreRules { get; set; }
/// <summary>
/// 精度
/// </summary>
public string MinPrecision { get; set; }
/// <summary>
/// 标称值
/// </summary>
public double? Stander { get; set; }
/// <summary>
/// 标称值
/// </summary>
public int? IsSaveHis { get; set; }
/// <summary>
/// 标称值
/// </summary>
public double? MaxVal { get; set; }
/// <summary>
/// 标称值
/// </summary>
public double? MinVal { get; set; }
/// <summary>
/// 标称值
/// </summary>
public int? IsControl { get; set; }
/// <summary>
/// 标称值
/// </summary>
public long? DataID { get; set; }
/// <summary>
/// 父数据ID
/// </summary>
public long? ParentDataID { get; set; }
}
1.2.3 原因分析
经过前端接口状态查询,数据库sql查询,日志逐级打印,最终定位某同步失败站点数据表PesudoDevice的content字段为空,原来应该为设备ID集合与协议模板解析规则。因为该设备协议模板较大,而序列化json比较耗时,此时设备的轮询报文到来,导致解析异常,从而程序崩溃。
1.2.4 解决方案
原因找准确了,解决方法其实很简单,只要把一开始解析异常的代码try catch异常。等解析规则存储完毕了,自然就能把信号点解析准确。
异常崩溃代码;
PseudoDeviceStatus data;
this.DPServiceObj.GetPseudoDeviceRealData(task.DstPseudoDeviceID, task.DstSignalID, out data );
解决异常代码:
PseudoDeviceStatus data=null;
try
{
this.DPServiceObj.GetPseudoDeviceRealData(task.DstPseudoDeviceID, task.DstSignalID, out data);
}
catch (Exception e)
{
log.ErrorFormat("获取设备实时数据失败:{0}",e);
}
分析问题时间用了很久,对问题理解透彻了以后,解决问题并不需要几行代码。
1.2.5 问题解决
数据同步成功结果
2. json长度限制带来的困惑
2.1 现象描述
随着站点(含待测点)添加越来越多,单次加载遇到瓶颈,无法将全部数据单次加载。
2.2 问题分析
2.2.1 第一步,查看对应告警预案接口,报服务器错误
2.2.2 第二步,查看接口返回结果预览
错误提示为返回字符串长度超过了json的默认最大长度,这个问题已经遇到过,设置下json序列化的最大长度即可轻松解决。
2.2.3 问题解决
问题代码
/// <summary>
/// 获取设备树
/// </summary>
/// <returns></returns>
public ActionResult GetAlarmPlanDevTree()
{
List<object> children = new List<object>();
List<Area> areas = DevicesTreeHelper.GetAreaStation();
foreach (Area a in areas)
{
children.Add(GetATreeData(a, true));
}
return Json(children);
}
问题解决代码
/// <summary>
/// 获取设备树
/// </summary>
/// <returns></returns>
public ActionResult GetAlarmPlanDevTree()
{
List<object> children = new List<object>();
List<Area> areas = DevicesTreeHelper.GetAreaStation();
foreach (Area a in areas)
{
children.Add(GetATreeData(a, true));
}
return new JsonResult() { Data = children, MaxJsonLength = int.MaxValue, ContentType = "application/json" };
}
解决之后所有测点信号加载成功
3. 小结
遇到问题并不可怕,只要能复现,根据具体提示,逐级打印日志,分析数据库,问题就能迎刃而解,在此做个记录,下次类似问题遇到能有印象,快速定位解决。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。