Страницы

Поиск по вопросам

среда, 1 января 2020 г.

Лучший способ подсчета времени в течении которого переменная не изменялась. C#

#c_sharp #net #winforms


Добрый день. Есть ли какой нибудь красивый способ отслеживания времени в течении
которого переменная не изменяла свое значение? На данный момент я реализовал это каким
то мерзким костылем.

        private double _zpreventValue;
        private readonly System.Windows.Forms.Timer _zcontrolTimer = new System.Windows.Forms.Timer();
        private readonly System.Windows.Forms.Timer _downtimeTimer = new System.Windows.Forms.Timer();
        private TimeSpan _downtime = new TimeSpan(0,0,0,0,0);

        private void FrmMain_Load(object sender, EventArgs e)
        {               
            _zcontrolTimer.Tick += _ZcontrolTimer_Tick;
            _zcontrolTimer.Interval = 5000;

            _downtimeTimer.Tick += _downtimeTimer_Tick;
            _downtimeTimer.Interval = 1000;  
        }

        private void _downtimeTimer_Tick(object sender, EventArgs e)
        {
            if (_zcontrolTimer.Enabled)
                BeginInvoke(new Action(() => _zcontrolTimer.Stop()));
            _downtime = _downtime + new TimeSpan(0,0,0,1);
            BeginInvoke(new Action(() => digitalGauge8.Text = _downtime.ToString()));

            using (var db = new VstecEntities())
            {
                 db.DownTimes.Single(item => item.Date == DateTime.Today).MachineDownTime
= _downtime;
                 db.SaveChanges();
            }
        }

        private void _ZcontrolTimer_Tick(object sender, EventArgs e)
        {
            using (var db = new VstecEntities())
            {
                if (db.DownTimes.Count(item => item.Date == DateTime.Today) == 0)
                {
                    db.DownTimes.Add(new DownTime
                    {
                        Date = DateTime.Today,
                        MachineDownTime = _downtime
                    });
                    db.SaveChanges();
                }                
            }

            BeginInvoke(new Action(() => _downtimeTimer.Start()));
        }

private void SomeFunc()
{
            if (Math.Abs(someValue - _zpreventValue) <= 0.0)
            {                
                if (!_zcontrolTimer.Enabled && !_downtimeTimer.Enabled)
                    BeginInvoke(new Action(() => _zcontrolTimer.Start()));
            }
            else
            {
                _zpreventValue = someValue;
                if (_zcontrolTimer.Enabled)
                    BeginInvoke(new Action(() => _zcontrolTimer.Stop()));
                if (_downtimeTimer.Enabled)
                    BeginInvoke(new Action(() => _downtimeTimer.Stop()));
            }    
}


Есть функция в которую прилетает какое то значение. Если значение равно значению
переменной, то запускается таймер, который ожидает 5 секунд и после чего запускает
еще один таймер(мрак) который начинает отсчет времени в течении которого переменная
не изменяет своего значения. Как только значение переменной меняется, таймер останавливается
и все по новой. 

Есть ли какой нибудь более элегантный способ? А то смотря на свои каракули хочется
плакать :(
    


Ответы

Ответ 1



На мой взгляд, достаточно завести свойство и счетчик времени к этому свойству. Счетчик перезапускается в момент изменения свойства. class Test { private Stopwatch stopwatch = Stopwatch.StartNew(); private int someValue; public int SomeValue { get { return someValue; } set { if (someValue != value) { someValue = value; OnSomeValueChanged(); } } } private OnSomeValueChanged() { stopwatch.Stop(); Console.WriteLine($"Свойство SomeValue не менялось {stopwatch.ElapsedMilliseconds} миллисекунд."); stopwatch = Stopwatch.StartNew(); } } При желании обобщить решение для разных свойств можно сделать реализацию INotifyPropertyChanged, подписаться на событие и завести, например, словарь с таймерами. UPD Добавил пример для нескольких свойств с запоминанием временных меток (по предложению @Андрей): class Test { private readonly stopwatch = Stopwatch.StartNew(); private readonly Dictionary labels = new Dictionary(); private str someValue1; public string SomeValue1 { get => someValue1; set { if (someValue1 != value) { someValue1 = value; HandlePropertyChanged(); } } } private str someValue2; public string SomeValue2 { get => someValue2; set { if (someValue2 != value) { someValue2 = value; HandlePropertyChanged(); } } } private void HandlePropertyChanged([CallerMemberName]string propertyName = null) { // если не нашли метку в словаре, то это свойство еще не менялось int lastLabel; if (!labels.TryGetValue(propertyName, out lastLabel)) { lastLabel = 0; } // запоминаем текущую метку var currentLabel = stopwatch.ElapsedMilliseconds; // получаем временной промежуток Console.WriteLine($"Прошло {currentLabel - lastLabel} миллисекунд."); // устанавливаем новую метку labels[propertyName] = currentLabel; } }

Комментариев нет:

Отправить комментарий