C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

SoundPlayerの破棄 /B.B (18/09/28(Fri) 08:16) #88790
Re[1]: SoundPlayerの破棄 /774RR (18/09/28(Fri) 09:30) #88791
Re[1]: SoundPlayerの破棄 /魔界の仮面弁士 (18/09/28(Fri) 09:54) #88792
  └ Re[2]: SoundPlayerの破棄 /B.B (18/09/28(Fri) 13:39) #88799 解決済み


親記事 / ▼[ 88791 ] ▼[ 88792 ]
■88790 / 親階層)  SoundPlayerの破棄
□投稿者/ B.B (1回)-(2018/09/28(Fri) 08:16:14)

分類:[C#] 

Windows10
Visual Studio 2017
C#

wavファイルを読み込んで音を鳴らすのに以下のようにしていました。
using (var player = new SoundPlayer(soundFile)) player.Play();

次のように変数に入れなくとも鳴ることに気づきました
new SoundPlayer(soundFile).Play();

この場合はDisposeしなくともすぐ破棄されるのでしょうか?
よろしくお願いします。
[ □ Tree ] 返信 編集キー/

▲[ 88790 ] / 返信無し
■88791 / 1階層)  Re[1]: SoundPlayerの破棄
□投稿者/ 774RR (628回)-(2018/09/28(Fri) 09:30:52)
参照カウント0のオブジェクトは gc がそのうち回収する、としか言えないので
・すぐ破棄されることもある
・ずっと残ることもある(数分とか数時間とか)
事前には、上記どちらもありうるとしか言えないっす。

実用上はいつ破棄されてもそんなに差支えないレベルの話だと思う。
IDisposable ってことはクラス内部にアンマネージリソースがあるわけだけど、
それを閉じるタイミングが重要(プログラマが意識しないといけない)なのであれば using が必須
ほぼどうでもよいなら using しなくても問題ないっす。
SoundPlayer はサウンドリソースを完全に読み込んでから演奏するとあるので、
サウンドファイルが Play() 時点でクローズ済みであることは期待してもよさそう。

オイラ的には提示ソースコードに関して次のことのほうが気になるっす。
- Play() で非同期演奏開始、
- その終了を待たずに即 Dispose 開始
- Dispose() は演奏終了まで待ってくれるのか? はたして最後まで演奏されるのか?

PlaySync() だったら気にならないとこだけど







[ 親 88790 / □ Tree ] 返信 編集キー/

▲[ 88790 ] / ▼[ 88799 ]
■88792 / 1階層)  Re[1]: SoundPlayerの破棄
□投稿者/ 魔界の仮面弁士 (1865回)-(2018/09/28(Fri) 09:54:06)
No88790 (B.B さん) に返信
> using (var player = new SoundPlayer(soundFile)) player.Play();

PlaySync メソッドではなく、
Play メソッドを使っている場合の話ですね。


> この場合はDisposeしなくともすぐ破棄されるのでしょうか?

そもそも SoundPlayer クラスは、Dispose をオーバーライドしていません。継承しているだけ。


実験用に、こんな感じのクラスを用意しておき、

class WavePlayer : System.Media.SoundPlayer {
  internal WavePlayer(string soundLocation) : base(soundLocation) { }
  internal WavePlayer(System.IO.Stream stream) : base(stream) { }
  protected override void Dispose(bool disposing) {
    System.Diagnostics.Debug.WriteLine($"SoundPlayer.Dispose({disposing})");
    base.Dispose(disposing);
  }
}

class WaveStream : System.IO.FileStream {
  internal WaveStream(string file) : base(file, System.IO.FileMode.Open, System.IO.FileAccess.Read) { }
  protected override void Dispose(bool disposing) {
   System.Diagnostics.Debug.WriteLine($"Stream.Dispose({disposing})");
   base.Dispose(disposing);
 }
}


呼び出し側をこんな感じに変更してみると、動作の違いが見えてくるかも。


private string soundFile = @"C:\windows\media\Alarm01.wav";

private void button1_Click(object sender, EventArgs e)
  => new WavePlayer(new WaveStream(soundFile)).Play();

private void button2_Click(object sender, EventArgs e) {
  using (var player = new WavePlayer(new WaveStream(soundFile))) player.Play();
}

private void button3_Click(object sender, EventArgs e) {
  using (var wave = new WaveStream(soundFile))
  using (var player = new WavePlayer(wave))
  {
    player.Play();
  }
}
[ 親 88790 / □ Tree ] 返信 編集キー/

▲[ 88792 ] / 返信無し
■88799 / 2階層)  Re[2]: SoundPlayerの破棄
□投稿者/ B.B (3回)-(2018/09/28(Fri) 13:39:05)
774RRさん、魔界の仮面弁士 さん返信ありがとうございます。

参照がなくなれば gc がそのうち回収する件、理解いたしました。

>- Play() で非同期演奏開始、
>- その終了を待たずに即 Dispose 開始
Dispose後にメッセージボックスを表示させても最後まで演奏されてます。

サンプルコードありがとうございます。
Disposeする意味がない感じです、ありがとうございました。
解決済み
[ 親 88790 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -