修正InterlockManager中的INTLK动作列表正在加载时,其它线程已经开始遍历该列表,导致异常的问题。

优化InterlockManager中的变量名称。
This commit is contained in:
SL 2023-12-27 16:13:36 +08:00
parent 66ddf8b742
commit 558af89d22
3 changed files with 43 additions and 31 deletions

View File

@ -18,12 +18,12 @@ public class InterlockDaemonManager : InterlockManagerBase<InterlockDaemonAction
public override void Monitor()
{
// 按Module扫描Interlock Limit
foreach (var moduleName in _dicActionsPerModule.Keys.ToList())
foreach (var moduleName in _dictINTLKActionsPerModule.Keys.ToList())
{
Debug.Assert(moduleName != ModuleName.UnDefined,
$"Interlock Manager CanSetDo() undesired module name {ModuleName.UnDefined}");
foreach (var action in _dicActionsPerModule[moduleName].ToList())
foreach (var action in _dictINTLKActionsPerModule[moduleName].ToList())
action.Monitor();
}
}

View File

@ -66,7 +66,7 @@ namespace Aitex.Core.RT.IOCore.Interlock
if (!succeeded)
return false;
_dicModulePostInfo = _dicLimitsPerModule.Keys.ToDictionary(x => x, x => false);
_dicModulePostInfo = _dictINTLKActionsPerModule.Keys.ToDictionary(x => x, x => false);
return true;
}
@ -76,7 +76,7 @@ namespace Aitex.Core.RT.IOCore.Interlock
public override void Monitor()
{
// 按Module扫描Interlock Limit
foreach (var moduleName in _dicLimitsPerModule.Keys.ToList())
foreach (var moduleName in _dictINTLKActionsPerModule.Keys.ToList())
{
Debug.Assert(moduleName != ModuleName.UnDefined,
$"Interlock Manager CanSetDo() undesired module name {ModuleName.UnDefined}");
@ -86,7 +86,7 @@ namespace Aitex.Core.RT.IOCore.Interlock
if (isBypassInterlock)
continue;
foreach (var limit in _dicLimitsPerModule[moduleName].ToList())
foreach (var limit in _dictLIMTPerModule[moduleName].ToList())
{
// 如果互锁没被触发
@ -96,10 +96,10 @@ namespace Aitex.Core.RT.IOCore.Interlock
var reverseInfo = new StringBuilder();
var module = "System";
if (!_dicLimitToActionMap.ContainsKey(limit))//新增判断集合中是否包含,防止异常报错
if (!_dictLIMT2INTLKActionMap.ContainsKey(limit))//新增判断集合中是否包含,防止异常报错
continue;
var actions = _dicLimitToActionMap[limit].ToList();
var actions = _dictLIMT2INTLKActionMap[limit].ToList();
foreach (var action in actions)
{
// 尝试根据Action定义复位该互锁限制条件对应的所有DO的电平
@ -171,11 +171,15 @@ namespace Aitex.Core.RT.IOCore.Interlock
if (isBypassInterlock)
return true;
if (_dictINTLKActionsFileLoader.TryGetValue((doName, onOff), out var ilAction))
ilAction.CanDo(out reason);
/*
foreach (var action in _lstActions.Where(action => action.IsSame(doName, onOff)))
{
return action.CanDo(out reason);
}
*/
return true;
}

View File

@ -1,9 +1,9 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceModel.Configuration;
using System.Text;
using System.Xml;
using Aitex.Core.RT.IOCore.Interlock.DataProvider;
@ -25,22 +25,22 @@ public abstract class InterlockManagerBase<TAction>
protected string RootNodeName;
protected readonly List<TAction> _lstActions;
protected readonly ConcurrentDictionary<(string actionName, bool doValue), TAction> _dictINTLKActionsFileLoader;
/// <summary>
/// 每个Limit对应的DoAction集合。
/// </summary>
protected readonly Dictionary<IInterlockLimit, List<IInterlockAction>> _dicLimitToActionMap;
protected readonly Dictionary<IInterlockLimit, List<IInterlockAction>> _dictLIMT2INTLKActionMap;
/// <summary>
/// 每个Module对应的DoAction集合。
/// </summary>
protected readonly Dictionary<ModuleName, List<TAction>> _dicActionsPerModule;
protected readonly Dictionary<ModuleName, List<TAction>> _dictINTLKActionsPerModule;
/// <summary>
/// 每个Module对应的Limit集合。
/// </summary>
protected readonly Dictionary<ModuleName, List<IInterlockLimit>> _dicLimitsPerModule;
protected readonly Dictionary<ModuleName, List<IInterlockLimit>> _dictLIMTPerModule;
#endregion
@ -51,10 +51,10 @@ public abstract class InterlockManagerBase<TAction>
/// </summary>
protected InterlockManagerBase()
{
_lstActions = new();
_dicActionsPerModule = new();
_dicLimitToActionMap = new ();
_dicLimitsPerModule = new ();
_dictINTLKActionsFileLoader = new();
_dictINTLKActionsPerModule = new();
_dictLIMT2INTLKActionMap = new ();
_dictLIMTPerModule = new ();
}
#endregion
@ -172,14 +172,14 @@ public abstract class InterlockManagerBase<TAction>
}
var moduleName = GetModuleFromIo(targetDo.Name);
if (!_dicActionsPerModule.ContainsKey(moduleName))
_dicActionsPerModule[moduleName] = new List<TAction>();
if (!_dictINTLKActionsPerModule.ContainsKey(moduleName))
_dictINTLKActionsPerModule[moduleName] = new List<TAction>();
// 创建InterlockAction对象首先判断该动作是否已经存在若存在则报错
var action = (TAction)Activator.CreateInstance(typeof(TAction), moduleName.ToString(),
targetDo, doValue, tip, dicTips);
if (_lstActions.Exists(x => x.IsSame(action.ActionName, doValue)))
if (_dictINTLKActionsFileLoader.ContainsKey((action.ActionName, doValue)))
{
var err = $"Interlock Action {action.ActionName}={doValue} duplicated in {configFile}";
LOG.Error(err);
@ -209,8 +209,16 @@ public abstract class InterlockManagerBase<TAction>
}
}
_dicActionsPerModule[moduleName].Add(action);
_lstActions.Add(action);
_dictINTLKActionsPerModule[moduleName].Add(action);
if (_dictINTLKActionsFileLoader.ContainsKey((action.ActionName, doValue)))
{
LOG.Error($"Duplicate interlock action definition: {action.ActionName}, {doValue}");
continue;
}
if(!_dictINTLKActionsFileLoader.TryAdd((action.ActionName, doValue), action))
LOG.Error($"Unable to add {action} to the ConcurrentDictionary");
// 如果当前Action设置了忽略翻转则不要注册Limit到当前Action的映射避免Limit触发导致Action翻转。
if (!ignoreReverse_All)
@ -220,21 +228,21 @@ public abstract class InterlockManagerBase<TAction>
if (!limit.IgnoreReverse)//如果单个limit也忽略反转不要注册Limit到当前Action的映射避免Limit触发导致Action翻转。
{
// 创建以Limit分组的Action字典
if (!_dicLimitToActionMap.ContainsKey(limit))
_dicLimitToActionMap[limit] = new List<IInterlockAction>();
if (!_dictLIMT2INTLKActionMap.ContainsKey(limit))
_dictLIMT2INTLKActionMap[limit] = new List<IInterlockAction>();
_dicLimitToActionMap[limit].Add(action);
_dictLIMT2INTLKActionMap[limit].Add(action);
}
}
}
}
Debug.Assert(!_dicActionsPerModule.ContainsKey(ModuleName.UnDefined),
$"InterlockManager {nameof(_dicActionsPerModule)} contains key {ModuleName.UnDefined}");
Debug.Assert(!_dictINTLKActionsPerModule.ContainsKey(ModuleName.UnDefined),
$"InterlockManager {nameof(_dictINTLKActionsPerModule)} contains key {ModuleName.UnDefined}");
Debug.Assert(!_dicLimitsPerModule.ContainsKey(ModuleName.UnDefined),
$"InterlockManager {nameof(_dicLimitsPerModule)} contains key {ModuleName.UnDefined}");
Debug.Assert(!_dictLIMTPerModule.ContainsKey(ModuleName.UnDefined),
$"InterlockManager {nameof(_dictLIMTPerModule)} contains key {ModuleName.UnDefined}");
}
catch (Exception ex)
{
@ -362,11 +370,11 @@ public abstract class InterlockManagerBase<TAction>
return null;
}
// 从_dicLimitsPerModule字典中查找当前创建的Limit是否已经存在
// 从_dictLIMTPerModule字典中查找当前创建的Limit是否已经存在
// 如果存在直接返回已存在的Limit实例
// 否则将当前创建的Limit放到字典中然后返回实例
var moduleName = GetModuleFromIo(limit.Name);
if (_dicLimitsPerModule.TryGetValue(moduleName, out var list))
if (_dictLIMTPerModule.TryGetValue(moduleName, out var list))
{
var existLimit = list.FirstOrDefault(x => x.UniqueId == limit.UniqueId);
if(existLimit != null)
@ -377,7 +385,7 @@ public abstract class InterlockManagerBase<TAction>
else
{
// 在字典中创建Module并将Limit实例放入字典
_dicLimitsPerModule[moduleName] = new List<IInterlockLimit>(new[] { limit });
_dictLIMTPerModule[moduleName] = new List<IInterlockLimit>(new[] { limit });
}
return limit;