如何检查每个计时器滴答中仅更改一次的属性?

问题描述

我使用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

的日志记录

timer logging

如何更改此设置,使其仅在每个计时器滴答时触发一次?

解决方法

我通过将逻辑从属性更改为另一种方法来修复它,在新代码中它是这样的:

    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