#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 Dictionarylabels = 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; } }
Комментариев нет:
Отправить комментарий