ここには簡単な質問があります:System.Media.SoundPlayerを使用して非同期にサウンドファイルを再生する方法
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()は非同期で、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のwhat's wrong with this code part 26を参照してください。
SoundPlayerにPlayAsyncCompletedイベントがあるようです。残念ながら、そのようなイベントは存在しません。何か不足していますか? Windowsフォームで.wav埋め込みリソースを非同期に再生する適切な方法は何ですか?
フィードバックいただきありがとうございます。私のアプリケーションは、リモートユーザが何らかのメッセージを送信したときにサウンドが再生される非同期RPCを備えたクライアント/サーバアプリケーションです。残念ながら、Ostermanが説明している問題とまったく同じです。私のアプリはシンプルではありませんが、「組み込みリソースから非同期にサウンドファイルを再生する」とは単純なシナリオです。 –
「組み込みリソースから非同期でサウンドファイルを再生する」というのは簡単なシナリオですが、リモートユーザーがメッセージを送信したときにサウンドを再生するという要件はありません。既にサウンドが再生されていて、新しいメッセージが届いていますか? (a)サウンドはすでに再生されているため、メッセージを無視しますか?その場合は、スレッドプールを使用せず、名前付きスレッドを使用し、スレッドがすでに実行中の場合は何もしないでください。スレッドが実行されていない場合は、起動します。 – BlueShepherd
(b) "SAME"の音が再び再生されるようにキューに入れますか?そうであれば、メッセージを受け取るたびに共有変数をインクリメントします(ゼロの場合はスレッドを開始します)。スレッドプールスレッドでは、メッセージを再生するたびに、ループ内の変数を減らします。 (c)別のサウンドをキューに入れますか?再生するサウンドを「ホールド」するためのキューを作成する必要があります。あなたがメッセージを受け取ったときにキューに音を入れて、それらを再生するときにそれらを取り除く – BlueShepherd