自定义了个获取SNMP节点值的方法,打算采用Parallel ForEach从有多个节点的列表中并行获取这些节点的值。在获取SNMP节点值的方法未采用异步方法时,程序运行正常。但是当尝试将获取SNMP节点值的方法改为异步方法后,虽然在此方法中做了异常处理,但是系统仍然报出未处理的异常。详情如下:
以下是GetSnmpValue方法中的关键语句,其中做了异常捕获。
//获取SNMP值的关键语句:
SnmpV1Packet result = null;
try
{
result = (SnmpV1Packet)target.Request(pdu, param);
}
catch (Exception ex)
{
MainLog($"获取SNMP值失败:{ex}", LogType.Error);
}
在如下并行同步调用此方法时,可正常处理异常。
//同步调用GetSnmpValue方法
try
{
Parallel.ForEach(oidList, new ParallelOptions { CancellationToken = token }, async tuple =>
{
// 获取Item1 IP地址的Item2节点的SNMP值
string OV = GetSnmpValue(tuple.Item1, tuple.Item2, getCommunity);
});
//其他相关处理
}
catch (Exception ex)
{
//在日志框里打印异常信息
MainLog($"获取SNMP值异常:{ex}", LogType.Error);
}
但在如下采用await Task.Run异步调用此方法时,GetSnmpValue方法中仍然报出未处理的异常,例如当目标IP不通时,显示达到最大尝试获取的次数,报出未处理的异常中断程序。
//异步调用GetSnmpValueAsync方法
try
{
Parallel.ForEach(oidList, new ParallelOptions { CancellationToken = token }, async tuple =>
{
// 获取Item1 IP地址的Item2节点的SNMP值
string OV = await Task.Run(() => GetSnmpValueAsync(tuple.Item1, tuple.Item2, getCommunity));
});
//其他相关处理
}
catch (Exception ex)
{
//在日志框里打印异常信息
MainLog($"获取SNMP值异常:{ex}", LogType.Error);
}
明明在原方法和并行方法中都做了异常处理,为什么获取不到异常呢?始终找不到原因,做了各种尝试,才总结出来,其实主要原因还是出在Parallel方法的异常处理方式上。Parallel方法需要采用AggregateException而不是普通的Exception来获取Parallel并行过程中所有引发的的异常。如下修改后即可正常捕获异常。而且还要注意:不能在原方法中throw异常,否则在throw位置会报出未处理的异常。
//异步调用GetSnmpValueAsync方法
try
{
Parallel.ForEach(oidList, new ParallelOptions { CancellationToken = token }, async tuple =>
{
// 获取Item1 IP地址的Item2节点的SNMP值
string OV = await Task.Run(() => GetSnmpValueAsync(tuple.Item1, tuple.Item2, getCommunity));
});
//其他相关处理
}
catch (AggregateException ex)
{
//在日志框里打印异常信息
MainLog($"获取SNMP值异常:{ex}", LogType.Error);
}