Очень странная ошибка при использовании System.Timers.Timer

По какой-то странной причине событие Elapsed срабатывает дважды, хотя определенно должно срабатывать один раз. И сразу после этого таймер перестает работать ... Структура кода примерно такая: Определенный объект определен для запуска определенного события, когда значение, которое он содержит, которое постоянно обновляется с интервалами 500-1500 мс, увеличивается на сумму более X по сравнению с предыдущим значением.

Например, если я определяю свой X как 2, а значения, которые я получаю, например, 1,2,1,2,3,4,8, событие сработает при вводе 8. Обработчик этого события запускает вышеупомянутый таймер, который работает в течение Y времени до истечения его срока, и запускает проблемное событие. Если значение возвращается к норме до истечения таймера, таймер сбрасывается.

Таким образом, общим результатом должно быть приложение, которое измеряет определенное динамическое значение и отслеживает его на предмет больших исключений размера X, которые происходят в течение более Y секунд.

Общий результат в коде выглядит примерно так

vMonitor.Range=X;
vMonitor.Over+= new EventHandler(StartTimer);
vMonitor.Normal+= new EventHandler(StopTimer);
vTimer.Elapsed+= new EventHandler(RaiseAlert);
source.BeginUpdate(vMonitor.Value);

Фактическая проблема заключается в том, что RaiseAlert срабатывает дважды по истечении таймеров, а затем создается впечатление, что таймер полностью перестает работать, больше не срабатывает. Я думаю, стоит упомянуть, что полное приложение содержит много потоковой активности, по крайней мере, с двумя запущенными одновременно потоками, обновляющими значения vMonitor.

Какие-нибудь мысли?

Обновлять:

Что касается потока, его довольно сложно объяснить точную структуру, но я могу сказать, что объект vMonitor содержится в другом объекте, который содержит значение обновления, которое постоянно изменяется различными потоками, конечно, контролируемым образом. . Каждый раз, когда значение родительского объекта обновляется, оно сравнивается с vMonitor, и запускается соответствующее событие. Значение в vMonitor впоследствии заменяется значением родительского объекта.

Обновлено: Я только что снова проверил, делегат vTimer.Elapsed содержит только один правильный обработчик событий.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 627
3

Ответы 3

Что ж, мой самый основной инстинкт состоял в том, что каким-то образом у вас действительно есть два подключения к событию Elapsed, что приводит к запуску двух событий. Я был пойман через это, иногда потому, что я добавил подключение событий вручную, когда оно уже было добавлено в конструкторе, или здесь есть некоторый аспект наследования, где подключение уже находится в базовом классе, и вы его повторяете в производном классе.

Конечно, если есть несколько потоков, это совсем другая игра!

Отредактируйте, чтобы учесть то, что сказал Митч, потому что я совершенно забыл, что это самый простой ответ. В методе, обрабатывающем событие Elapsed, убедитесь, что вы сначала останавливаете свой таймер, чтобы событие не сработало снова, пока оно обрабатывается.

От MSDN:

The Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. Thus, the event handler should be reentrant.

Другие вопросы по теме