簡體   English   中英

如何使用System.Media.SoundPlayer異步播放聲音文件?

[英]How to use System.Media.SoundPlayer to asynchronously play a sound file?

這是一個看似簡單的問題:

在Windows窗體中異步播放嵌入式.wav資源文件的正確方法是什么?

嘗試#1:

var player = new SoundPlayer();
player.Stream = Resources.ResourceManager.GetStream("mySound");
player.Play(); // Note that Play is asynchronous
  • 好:不阻止UI線程
  • 錯誤:SoundPlayer和嵌入的資源流不會立即處理。

嘗試#2:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.Play();
    }
}
  • 好:未阻止UI線程,立即處理SoundPlayer和音頻內存流。
  • 壞:競爭條件! Play()是異步的,如果音頻內存在播放完成之前被釋放...繁榮! 拋出運行時異常。

嘗試#3:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.PlaySync();
    }
}
  • 好:播放器和音頻流立即處理。
  • 錯誤:PlaySync會阻止UI線程

嘗試#4:

ThreadPool.QueueUserWorkItem(ignoredState =>
  {
    using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
    {
        using (var player = new SoundPlayer(audioMemory))
        {
            player.PlaySync();
        }
    }
  });
  • 好:UI不會凍結,播放器和內存流會立即處理掉。
  • 壞:因為這經常發生,我們可能會用盡線程池線程! 請參閱Larry Osterman 這段代碼26的錯誤

看起來SoundPlayer應該有一個PlayAsyncCompleted事件。 不幸的是,不存在此類事件。 我錯過了什么嗎? 在Windows窗體中異步播放.wav嵌入式資源的正確方法是什么?

我沒有足夠的聲譽來評論,所以我只是回答。

如果您播放聲音的要求“看似簡單”(您只想在單個winform用戶執行某些操作時偶爾播放聲音),那么我將使用上面的嘗試#4。

拉里·奧斯特曼(Larry Osterman)的“這個代碼部分26有什么問題”讓他的“系統”在每次按鍵時都會關閉一個新的線程池線程(播放聲音)。 他指出,在敲打它的過程中,在大約15秒內打破了默認的500線程池大小,但這也是使用異步RPC同時使用線程池的客戶端/服務器應用程序。 真的不是一個“看似簡單”的應用程序。

如果您嘗試每秒(或更快)將聲音字節排隊10秒或100秒,那么它實際上不是“簡單應用程序”,排隊的線程/優先級子系統可能是有序的。

我仍然使用win32 API中的ol'waveOut____函數。 這是一個很好的代碼示例:

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

編輯 :一個更簡單的問題解決方案是提取嵌入的資源,將其保存為某個地方的真實文件,然后使用SoundPlayer播放該文件。 有點笨重,但很簡單,你不會有資源處理問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM