0

недавно начал изучать C# и программирование в целом. Хочу сделать в качестве учебного проекта метроном в консольном приложении, постепенно добавляя новые функции.

На первом этапе хочу сделать проигрывание звука метронома с заданной скоростью и возможностью в реальном времени убавлять\прибавлять темп клавишами - +, и ставить на паузу и продолжать работу при нажатии пробела в зависимости от текущего состояния метронома. Точность таймера пока непринципиальна. Для проигрывания звука использую System.Timers

Выглядит черновик выглядит примерно так:

class Program
    {
        static void Main(string[] args)
        {
            Metronome metronome = new Metronome();
            metronome.Start();
        Console.ReadKey();
    }
  }

public class Metronome { private SoundPlayer player = new SoundPlayer(); private Timer playerTimer = new Timer();

private int bpm = 120;
private int interval;
private bool isRunning = true;

public Metronome()
{
    playerTimer.Elapsed += OnTimeElapsed;
    playerTimer.Interval = 60000 / bpm;
}

private void OnTimeElapsed(object? sender, ElapsedEventArgs e)
{
    player.Play();
    Console.WriteLine("Sound is played, add sound path later");          
}

public void Start()
{
    while (isRunning)
    {
        playerTimer.Start();
    }
}

private void Pause()
{
    //Pause
}

private void UnPause()
{
    //Unpause
}

}

Возник вопрос, чтобы не загружать процессор имитацией полезной цикла во время ожидания нажатия клавиши, хотелось бы сделать так, чтобы проверка на ввод проводилась 60 раз в секунду.

Подскажите какими способами можно сделать? Из знакомых для меня это пока Sleep и еще один таймер.

Про Sleep читал, что его не следует использовать, особенно, если добавить графический интерфейс. С таймером получается немного запутанный код.

Интересует какими методами сейчас реализуются в приложениях подобные ограничения, когда максимальная скорость выполнения цикла не нужна, а требуется минимально необходимое использование процессора?

Спасибо.

  • Асинхронность с Task.Delay() в помощь. – EvgeniyZ Jan 24 '23 at 19:36
  • 1, 2. Здесь главная проблема в том, что ни Thread.Sleep(x), не await Task.Delay(x) вам не дадут точных временных отсечек, будет отклонение в бОльшую сторону. У Sleep поменьше, у Delay побольше. Подсказка в ответе по первой ссылке. – aepot Jan 24 '23 at 21:41
  • 1 - ReadKey не нагружает процессор. 2 - цикл не нужен: таймер запускается 1 раз. Главное, чтобы AutoReset стоял. – Иван Jan 25 '23 at 04:25
  • @aepot спасибо. Точность пока не принципиальна, поскольку сам метроном, является эталонными часами. Если конечно, его сравнивать с другими часами то погрешность станет заметна, но пока это не важно. Мне важно понять, какие есть хорошие практики того как можно ограничить цикл while(true). Насколько я читал информацию, что он максимально использует ресурсы процессора. То есть мне нужно, проверять с частотой 60 раз в секунду, был ли нажат пробел. – Zanjiin Jan 25 '23 at 04:39
  • @EvgeniyZ спасибо. – Zanjiin Jan 25 '23 at 04:44
  • хочу ... убавлять\прибавлять темп клавишами ... ставить на паузу и продолжать работу - это уже сделано? Покажите код. Или проблема как раз в реализации этого? А вовсе не в таймере? – Alexander Petrov Jan 25 '23 at 12:01
  • @AlexanderPetrov Это пока не сделано, но проблема не в реализации этих функций, я примерно знаю как это сделать. Вопрос был в том, какими способами делают минимальное использование ресурсов, чтобы к примеру проверка буфера клавиатуры выполнялась лишь несколько раз в секунду. К примеру, как запускаете пустую WinForms, она висит и берет лишь самый минимум. (кроме Thread.Sleep) – Zanjiin Jan 25 '23 at 13:34
  • Console.KeyAvailable и Console.ReadKey достаточно для решения задачи. – Alexander Petrov Jan 25 '23 at 13:40

0 Answers0