Как использовать System.Media.SoundPlayer для асинхронного воспроизведения звукового файла? - PullRequest
13 голосов
/ 21 июля 2009

Вот обманчиво простой вопрос:

Как правильно воспроизвести встроенный файл ресурсов .wav в Windows Forms?

Попытка № 1:

var player = new SoundPlayer();
player.Stream = Resources.ResourceManager.GetStream("mySound");
player.Play(); // Note that Play is asynchronous
  • Хорошо: не блокирует поток пользовательского интерфейса
  • Плохо: SoundPlayer и встроенный Поток ресурсов не сразу расположенный.

Попытка № 2:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.Play();
    }
}
  • Хорошо: поток пользовательского интерфейса не заблокирован, SoundPlayer и поток аудиопамяти немедленно удаляются.
  • Плохо: состояние гонки! Play () работает асинхронно, и если аудиопамять удаляется до того, как воспроизведение завершено ... бум! Исключение во время выполнения.

Попытка № 3:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.PlaySync();
    }
}
  • Хорошо: проигрыватель и аудиопоток немедленно удаляются.
  • Плохо: PlaySync блокирует поток пользовательского интерфейса

Попытка № 4:

ThreadPool.QueueUserWorkItem(ignoredState =>
  {
    using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
    {
        using (var player = new SoundPlayer(audioMemory))
        {
            player.PlaySync();
        }
    }
  });
  • Хорошо: пользовательский интерфейс не зависает, проигрыватель и поток памяти немедленно удаляются.
  • Плохо: поскольку это происходит часто, у нас могут заканчиваться потоки пула потоков! Посмотрите на Ларри Остермана , что не так с этой частью кода 26 .

Кажется, что SoundPlayer должен иметь событие PlayAsyncCompleted. К сожалению, такого события не существует. Я что-то пропустил? Как правильно воспроизводить встроенный ресурс .wav в Windows Forms?

Ответы [ 2 ]

6 голосов
/ 22 июля 2009

У меня недостаточно репутации, чтобы комментировать, поэтому я просто отвечу.

Если ваши требования к воспроизведению звука «обманчиво просты» (вы просто хотите воспроизвести случайный звук, когда один пользователь winform что-то делает), тогда я использовал бы попытку № 4 выше.

Ларри Остерман "Что не так с этой частью кода 26" заставляет свою "систему" вращать новый поток пула потоков (для воспроизведения звука) при каждом нажатии клавиши. Он указывает, что чем больше он забил, тем больше размер пула 500 потоков по умолчанию примерно за 15 секунд ввода, но это было также в приложении клиент / сервер, использующем асинхронный RPC, который также использовал пул потоков. Действительно не «обманчиво простое» приложение.

Если вы пытаетесь поставить в очередь звуковые байты каждую секунду (или быстрее) на 10 или 100 секунд за один раз, тогда это действительно не «простое приложение», и подсистема потоков / приоритетов в очереди, вероятно, будет в порядке.

2 голосов
/ 21 июля 2009

Я все еще использую старые добрые функции waveOut____ из win32 API. Вот хороший пример кода:

http://www.codeproject.com/KB/audio-video/cswavplay.aspx

Редактировать : гораздо более простое решение вашей проблемы - извлечь встроенный ресурс, сохранить его как настоящий файл где-нибудь и затем использовать SoundPlayer для воспроизведения файла. Немного неуклюже, но просто, и у вас не будет проблем с утилизацией ресурсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...