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