问题描述
我使用2个计时器,1每秒检查我所有的Vijeo Citect标记的值是否更改。另一个是用于TCP连接的KeepAlive计时器。
这就是我所说的计时器:
Timer timer = new Timer(ctApiCtrl.CheckUpdateallInputTags,"updatetags",1000,1000);
Timer timer2 = new Timer(mepCtrl.KeepAlive,"test",3000,3000);
现在,由于现有系统如何协同工作,因此需要写入和读取PLC / DSK标签。因此,如果我的服务要检测这些更改,则需要定期“轮询”或检查这些值。
这是这些标记来自的类:
public class TagWithValue : INotifyPropertyChanged
{
public string TagName { get; set; }
private string tagValue;
public TagCategory TagCategory { get; set; }
public string TagValue
{
get { return tagValue; }
set
{
if(tagValue != value)
{
tagValue = value;
RaisePropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this,new PropertyChangedEventArgs(prop));
}
}
因此,当属性TagValue
更改时,它会检测到它并触发x。
public void CheckUpdateallInputTags(object objectInfo)
{
VDGSenseController.Authenticate();
if (listofTags.Video == null || listofTags.Audio == null)
{
Logger.Info("Empty Tag list,reinitliazing all tags");
InitiliazeAllTags();
}
foreach (var tag in Tags)
{
try
{
var value = TagRead(tag.TagName); //read Tag value
tag.TagValue = value;
tag.PropertyChanged += d_PropertyChanged;
}
catch (Exception ex)
{
Logger.Warn(ex,"Importing tag unsuccesfull");
continue;
}
}
Tags = Tags.Where(t => !string.IsNullOrWhiteSpace(t.TagValue)).distinct().ToList();
}
这是此代码段的问题。
private void d_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
//trigger wanneer prop value is changed
var tagchanged = (CtModel.TagWithValue)sender;
Logger.Info($"Tag: {tagchanged.TagName} with value: {tagchanged.TagValue} has changed.");
}
此代码的问题在于,它会在同一计时器滴答中多次触发属性更改方法。
请注意包含标签DK_OM_2A
的日志记录如何更改此设置,使其仅在每个计时器滴答时触发一次?
解决方法
我通过将逻辑从属性更改为另一种方法来修复它,在新代码中它是这样的:
private void d_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
//trigger wanneer prop value is changed
var tagchanged = (CtModel.TagWithValue)sender;
tagsWithChangedValue.Add(tagchanged);
tagsWithChangedValue = tagsWithChangedValue.Distinct().ToList();
}
#region UpdateTagsPropertyChanged
public void UpdateTagsPropertyChanged(List<CtModel.TagWithValue> listofchangedtags)
{
if(listofchangedtags.Count == 0)
{
return; // if list is empty,go back
}
foreach(var tagchanged in listofchangedtags)
{
logger.Info($"Tag: {tagchanged.TagName} with value: {tagchanged.TagValue} has changed.");
switch (tagchanged.TagName)
{
default:
break;
}
}
tagsWithChangedValue.Clear(); //clears list for the next cycle
}
#endregion