Таймер.NET не выполняет обратный вызов, когда машина загружена очень интенсивно
Я использую System.Timers.Timer
для обратного вызова через каждые несколько секунд. Обратный вызов в основном отправляет сообщения непрерывного пульса на подключенный сервер.
Если сообщения пульса не отправляются в течение n секунд, сервер отключает их от подключенного клиента.
То, что я заметил, что, когда пользовательская машина очень сильно использует ресурсы, такие как - 100% загрузка ЦП и почти 95% использования памяти и система не реагирует на взаимодействие с пользователем, обратный вызов Timer не вызывается.
Я тоже пробовал с System.Threading.Timer
но не повезло, получая такой же результат.
Что является лучшим способом в.NET, чтобы убедиться, что ваше действие запускается независимо от использования ресурсов компьютера.
Заметка,
- Эта реализация работает просто идеально при нормальных сценариях.
- Я не использую потоки пользовательского интерфейса из моего приложения Windows для вызова обратного вызова, он использует фоновый (не-пользовательский) поток.
3 ответа
Похоже, что ваше периодическое сердцебиение является чем-то очень важным для вашего приложения, может быть даже более важным, чем отзывчивость пользовательского интерфейса и другие проблемы.
В таких случаях в системах реального времени обычно создают выделенный поток для этого с высоким приоритетом.
Итак, попробуйте создать выделенный поток (не BackgroundWorker, а новый System.Threading.Thread), придать ему высокий приоритет (ThreadPriority.Highest) и отправить контрольные сигналы из этого приоритетного потока.
Последний подход, который я выбрал -
- Увеличьте продолжительность частоты пинга (сердцебиение) с существующих n секунд до 3 * n секунд.
- Отправьте сообщение ping из темы с высоким приоритетом.
Я должен признать, что это все еще не решает проблему, а просто пытается задержать сбой.
Ответ на вопрос "Каков лучший способ в.NET убедиться, что ваше действие вызывается независимо от использования ресурсов компьютера". зависит от вашего определения "независимо".
Этот вопрос лежит в области вычислений в реальном времени.
Если вы пытаетесь использовать C# в Windows, я боюсь, что самая близкая к вам цель - поставить поток на приоритет в реальном времени, а затем использовать SpinWait между вызовами. В результате ваш поток займет 100% использования одного ядра.
Даже тогда есть проблемы со временем, с которыми вы можете иметь проблемы.
Возможно, вы захотите взглянуть на использование ОС реального времени и программы на C++.
Однако оба эти решения чрезвычайно дороги.
Однако я бы посоветовал вам устранить истинную суть проблемы, заключающуюся в том, что ваше приложение явно неэффективно использует потоки. Возможно, вы захотите переписать все ваше приложение с асинхронным вводом-выводом, что должно снизить загрузку процессора.
Вы также можете попробовать масштабировать ваше приложение по горизонтали. Но ясно, что ваша система переросла коробку.