Более точная альтернатива Thread.Sleep(1) - C#
Формулировка задачи:
Как подсказывает мне гугл, Thread.Sleep - это зло во плоти, атата, руки оторвут, и т.д.
Раньше проблем не было, пока не возникла следующая задача: мультипотоковое приложение c бесконечными циклами с настраиваемыми задержками шагом 1 мс.
Принципиальная схема говнокодерская и выглядит так:
Что было обнаружено:
И я вижу абсолютно такую же историю. Любая задержка от 1 до 15 включительно выглядит, как 15 мс. Разница начинает быть видна от 16 и далее. Кроме того, задержка самого потока тоже тормозит его работу на 15 мс в случае, если delay не равна нулю.
Мне же нужно, чтобы поток реагировал с точностью в 1 мс, и чтобы дополнительную задержку можно было ставить с шагом 1 мс.
Если вообще убрать sleep(1), всё работает безупречно. Скорость реакции потока на внешние раздражители, которые он и обрабатывает - десятая доля миллисекунды. Настройка доп.задержки - идеальная точность, плюс-минус десять тиков. НО. Поток грузит cpu.
Вопрос - как добиться того, чтобы поток работал "почти" в реальном времени (с задержкой реакции 1 мс или меньше), дополнительная задержка работала с точностью 1 мс, но при этом поток не грузил CPU на 100% ?
// класс-наследник от BackgroundWorker, переопределяет метод: protected override void OnDoWork(DoWorkEventArgs e) { while (true) { if (delay > 0) { stopwatch.Start(); while (stopwatch.Elapsed.Milliseconds < delay) { Thread.Sleep(1); } stopwatch.Reset(); } // обработка некоих данных, поступающих извне Thread.Sleep(1); //ради того, чтобы отпустить CPU и не грузить его на 100% } }
But beware: Windows is not a real-time OS, so you will not get 1000 wakes per second from Thread.Sleep(1). If you haven't used timeBeginPeriod to set your minimum resolution you'll wake about every 15 ms.
Решение задачи: «Более точная альтернатива Thread.Sleep(1)»
textual
Листинг программы
using System; using System.Threading; using System.Timers; using Timer = System.Timers.Timer; namespace ConsoleApplication23 { class Program { private static int i = 0; static void Main(string[] args) { var timer = new Timer(1); timer.Elapsed += (_, __) => { if (i > 0) Console.WriteLine(i); }; timer.Start(); Console.ReadKey(); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д