Как я могу выполнить неблокирующий System.Beep()?

В С# я могу выполнить Console.Beep(). Однако, если вы укажете продолжительность 1000 или 1 секунду, она не выполнит следующую строку кода до тех пор, пока эта секунда не пройдет.

Можно ли каким-либо образом выполнить Console.Beep() в неблокирующем режиме, чтобы он продолжал звучать и продолжал выполнять код под ним во время звукового сигнала?

Ответ 1

Вы можете запустить его в отдельном потоке.

new Thread(() => Console.Beep()).Start();

Я проснулся сегодня утром, чтобы найти шквал комментариев по этому вопросу. Поэтому я подумал, что буду перекликаться с некоторыми другими идеями.

Вышеупомянутое также может быть достигнуто запустив поток в пуле потоков, используя следующее.

Action beep = Console.Beep;
beep.BeginInvoke((a) => { beep.EndInvoke(a); }, null);

Важно, что в приведенном выше коде нужно вызвать EndInvoke для вашего делегата, если вы используете BeginInvoke, иначе вы столкнетесь с утечками памяти.

Из MSDN: Важно. Всегда вызывайте EndInvoke для завершения асинхронного вызова. http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.80).aspx

В качестве альтернативы вы можете использовать выделенный поток Beep для подачи звуковых сигналов в фоновом режиме по запросу без создания нового потока каждый раз или с использованием пула потоков (см. комментарий Саймона Чадвика). В качестве простого примера вы можете иметь следующее. Обратите внимание, что я передаю 1 как maxStackSize, это гарантирует, что для этого потока будет выполнено минимальное (не 1, минимальное) пространство стека, см. MSDN для более подробной информации об этом.

  class BackgroundBeep
  {
    static Thread _beepThread;
    static AutoResetEvent _signalBeep;

    static BackgroundBeep()
    {
      _signalBeep = new AutoResetEvent(false);
      _beepThread = new Thread(() =>
          {
            for (; ; )
            {
              _signalBeep.WaitOne();
              Console.Beep();
            }
          }, 1);
      _beepThread.IsBackground = true;
      _beepThread.Start();      
    }

    public static void Beep()
    {
      _signalBeep.Set();
    }
  }

При этом все, что вам нужно сделать, чтобы запустить фоновый звуковой сигнал в любое время без создания новых потоков, вызывает следующий вызов

BackgroundBeep.Beep();

Ответ 2

Вы можете использовать SoundPlayer.Play() и асинхронно раздражать пользователя чем-то, что звучит лучше, чем BEEP.

Ответ 3

Возможно, мне что-то не хватает, но почему бы не использовать:

System.Media.SystemSounds.Beep.Play();

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

Ответ 4

Здесь ресурсосберегающий способ воспроизведения звукового сигнала асинхронно:

Action beep = Console.Beep;
beep.BeginInvoke(null, null); 

Ответ 5

Вы можете использовать следующий код для запуска Console.Beep() в другом потоке:

System.Threading.Thread thread = new System.Threading.Thread(
    new System.Threading.ThreadStart(
        delegate()
        {
            Console.Beep();
        }
    ));

thread.Start();

Ответ 6

Вы можете запустить Console.Beep в отдельном потоке.