SoundPlayer

  • Thread starter Thread starter mick
  • Start date Start date
M

mick

Can someone explain why the soundplayer still works after a Dispose() call

SoundPlayer player = new SoundPlayer();
player.Stream = Properties.Resources.alarm;
player.Play();
player.Dispose();
player.Play() // Should this still work???
mick
 
Can someone explain why the soundplayer still works after a Dispose() call

SoundPlayer player = new SoundPlayer();
player.Stream = Properties.Resources.alarm;
player.Play();
player.Dispose();
player.Play()                // Should this still work???
mick

From memory, I've had problems with sound unless I stick to the
script. And when you play with Dispose you are overriding the
automatic garbage collection, which in C# has its own problems. Why
not just stick to the script? Follow the template in your textbook
and be done with it. MacDonald is a good author. Liberty as well.
Several others. Don't stray outside the safe boundaries they have
established.

RL
 
RayLopez99 said:
And when you play with Dispose you are overriding the
automatic garbage collection, which in C# has its own problems.

RL

Mind clarifying that comment? By "play with Dispose", do you mean
calling Dispose and then continuing to make use of the object? Or
calling Dispose at all? Generally, if an object implements Dispose, you
SHOULD call it once you are done using the object.

-Adam
 
mick said:
Can someone explain why the soundplayer still works after a Dispose() call

SoundPlayer player = new SoundPlayer();
player.Stream = Properties.Resources.alarm;
player.Play();
player.Dispose();
player.Play() // Should this still work???

There is actually no requirement that a call to Dispose() should render
an object unusable, either partially or completely.

That said, in this particular case, looking in Reflector I don't see any
implementation in SoundPlayer for the Dispose() method, in spite of what
the docs say (they claim that the Dispose(bool) overload is overridden
in SoundPlayer). So calling Dispose() doesn't do anything at all to any
of the SoundPlayer-specific functionality. I suppose it's possible that
something in the base class Component might no longer work after a call
to Dispose(), but something like the Play() method has no obvious reason
_not_ to continue working after you call Dispose().

Of course, the big question is: why are you calling Dispose() before
you're done with the object? :) Hopefully your question is simply
academic, and isn't related to a problem you're having in your code.

Pete
 
SoundPlayer player = new SoundPlayer();
player.Stream = Properties.Resources.alarm;
player.Play();
player.Dispose();
player.Play() // Should this still work???

I am not sure how the SoundPlayer works, but the main reason it might still
play is you have not stopped anything prior to dispose (closed the stream).
That would stop the object from being properly marked for disposal and it
would not dispose.

Peace and Grace,

--
Gregory A. Beamer (MVP)

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

*******************************************
| Think outside the box! |
*******************************************
 
Should it work? --You can resurect your object (and I would let others to
explain it), but that is probably NOT what you WANT, neither it is not
related to your first question.

It is quite possible that your SoundPlayer simply continue to play the
buffered 'sound'. In fact, if it would not, you would likely be hearing
nothing, (Play( ) does not *wait* to reach the end of the stream to
continue the execution of the calling code! It generates the sound from
another thread). It seems that you should call the Stop method to explicitly
'kill' (pause for an infinite amount of time) the sound.
http://msdn.microsoft.com/en-us/library/system.media.soundplayer.stop.aspx

Vanderghast, Access MVP

Can someone explain why the soundplayer still works after a Dispose() call

SoundPlayer player = new SoundPlayer();
player.Stream = Properties.Resources.alarm;
player.Play();
player.Dispose();
player.Play() // Should this still work???
mick
 
Peter Duniho said:
There is actually no requirement that a call to Dispose() should render
an object unusable, either partially or completely.

That said, in this particular case, looking in Reflector I don't see any
implementation in SoundPlayer for the Dispose() method, in spite of what
the docs say (they claim that the Dispose(bool) overload is overridden
in SoundPlayer). So calling Dispose() doesn't do anything at all to any
of the SoundPlayer-specific functionality. I suppose it's possible that
something in the base class Component might no longer work after a call
to Dispose(), but something like the Play() method has no obvious reason
_not_ to continue working after you call Dispose().

Of course, the big question is: why are you calling Dispose() before
you're done with the object? :)

Well the little program I used it in would use it for click sounds when a button
was pressed. This would be a rare occurance (if at all) so what i was doing
was creating a Soundplayer, using it, then disposing rather creating one at the
start of the prog and using that when and if I needed it. (Note - this was from
when I was learning about .Net and C# and was probably learning about Dispose())
Hopefully your question is simply
academic, and isn't related to a problem you're having in your code.

:-) Yes, it was simply something I`d noticed when messing aound with this old
piece of code. When I first learned about the SoundPlayer I`m almost certain
that the article I learnt it from said you *should* use Dispose() after you were
finished with it. I thought I`d try to see what happened after the Dispose and
was surprised to find it still worked. Just for clarity then (for me) Do I need
to Dispose of this oject myself or does the GC do it for me? I also remember
watching one of those MSN Webcast series which, again, I`m almost certain
said that if you`re not sure which objects you should dispose of yourself
then check to see if it exposes the Dispose method.

mick
 
Gregory A. Beamer said:
I am not sure how the SoundPlayer works, but the main reason it might still
play is you have not stopped anything prior to dispose (closed the stream).
That would stop the object from being properly marked for disposal and it
would not dispose.

What this snippet doesnt make clear is that the sound is actually finished playing
when the Dispose() is called as I was actually stepping through the code in the
debugger.

mick
 
mick said:
[...]
Just for clarity then (for me) Do I need
to Dispose of this oject myself or does the GC do it for me? I also remember
watching one of those MSN Webcast series which, again, I`m almost certain
said that if you`re not sure which objects you should dispose of yourself
then check to see if it exposes the Dispose method.

What you should check for is IDisposable. For example:

object someObject = ...;

later:

IDisposable disposable = someObject as IDisposable;

if (disposable != null)
{
disposable.Dispose();
}

How exactly that code will look depends a lot on the lifetime of the
object. If it's used only locally, then a "using" statement is best.
Otherwise, you need to track the lifetime of the object in some sensible
way, and make sure you call Dispose() before you lose track of the object.

Note that in many cases, you know the exact type of the object, and thus
already know whether it implements IDisposable or not, and thus can just
go ahead and call Dispose() directly, without checking for the
implementation (for some objects – those that implement IDisposable
explicitly rather than implicitly – you'll have to cast them to
IDisposable to access the Dispose() method).

In any case, the phrase "when you are finished with it" hides a lot of
potential complexity. In the SoundPlayer example, it's reasonable to
assume that you might want to pre-load a sound, and then keep that
pre-loaded SoundPlayer instance around so that you can play the sound
any time you like. In that case, you wouldn't dispose the instance
until you are sure you won't need to play that sound again. That might
actually be when your program is shutting down!

In any case, yes…you should always dispose your objects somehow. And
that's true even if you happen to find out that for a particular object,
the Dispose() method turns out to be a NOP. You never know when the
object implementation might change. If it implements IDisposable,
that's its way of telling you that you do need to dispose it when you're
finally through with it.

Properly implemented IDisposable objects will also have a finalizer,
which will allow the GC to dispose the object for you if you should
happen to forget _and_ the object becomes unreachable (i.e.
collectable). But you shouldn't rely on that; it's a backstop for the
object, not for your own code to depend on. Garbage collection and
object finalization happens on a non-deterministic basis; even if the
object does get finalized, it's less efficient to let the GC finalize
objects than to dispose them explicitly. And there is actually no
guarantee the GC will ever actually dispose and collect your object.

Pete
 
What this snippet doesnt make clear is that the sound is actually
finished playing when the Dispose() is called as I was actually
stepping through the code in the debugger.

This is inconsequential, as what you perceive and what the computer
"thinks" are two different things. As you are not in control of garbage
collection or the compiler, there are rules deeper than your code that are
in order. WIthout me playing with the code, I cannot guarantee this is the
case, but I have a strong suspicion.

I guess the more important questions is "why is it important that code to
run a sound after dispose fail?". You are in control of the code and
setting up the condition. Why set up something you know should not work
(from a human standpoint)?

Peace and Grace,

--
Gregory A. Beamer (MVP)

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

*******************************************
| Think outside the box! |
*******************************************
 
Gregory A. Beamer said:
This is inconsequential, as what you perceive and what the computer
"thinks" are two different things. As you are not in control of garbage
collection or the compiler, there are rules deeper than your code that are
in order. WIthout me playing with the code, I cannot guarantee this is the
case, but I have a strong suspicion.

I guess the more important questions is "why is it important that code to
run a sound after dispose fail?". You are in control of the code and
setting up the condition. Why set up something you know should not work
(from a human standpoint)?

It isn`t. I noticed that it happened and was curious as to the explanation.

mick
 
Peter Duniho said:
mick said:
[...]
Just for clarity then (for me) Do I need
to Dispose of this oject myself or does the GC do it for me? I also remember
watching one of those MSN Webcast series which, again, I`m almost certain
said that if you`re not sure which objects you should dispose of yourself
then check to see if it exposes the Dispose method.

What you should check for is IDisposable. For example:

object someObject = ...;

later:

IDisposable disposable = someObject as IDisposable;

if (disposable != null)
{
disposable.Dispose();
}

How exactly that code will look depends a lot on the lifetime of the
object. If it's used only locally, then a "using" statement is best.
Otherwise, you need to track the lifetime of the object in some sensible
way, and make sure you call Dispose() before you lose track of the object.

Note that in many cases, you know the exact type of the object, and thus
already know whether it implements IDisposable or not, and thus can just
go ahead and call Dispose() directly, without checking for the
implementation (for some objects – those that implement IDisposable
explicitly rather than implicitly – you'll have to cast them to
IDisposable to access the Dispose() method).

In any case, the phrase "when you are finished with it" hides a lot of
potential complexity. In the SoundPlayer example, it's reasonable to
assume that you might want to pre-load a sound, and then keep that
pre-loaded SoundPlayer instance around so that you can play the sound
any time you like. In that case, you wouldn't dispose the instance
until you are sure you won't need to play that sound again. That might
actually be when your program is shutting down!

In any case, yes…you should always dispose your objects somehow. And
that's true even if you happen to find out that for a particular object,
the Dispose() method turns out to be a NOP. You never know when the
object implementation might change. If it implements IDisposable,
that's its way of telling you that you do need to dispose it when you're
finally through with it.

Properly implemented IDisposable objects will also have a finalizer,
which will allow the GC to dispose the object for you if you should
happen to forget _and_ the object becomes unreachable (i.e.
collectable). But you shouldn't rely on that; it's a backstop for the
object, not for your own code to depend on. Garbage collection and
object finalization happens on a non-deterministic basis; even if the
object does get finalized, it's less efficient to let the GC finalize
objects than to dispose them explicitly. And there is actually no
guarantee the GC will ever actually dispose and collect your object.

Am I being misled? Why is there a GC.Collect() method if there is supposedly
no way to control the GC? I figure that GC.Collect() will collect all garbage
and that regular calls to it will dispose every unused object, even
IDisposables.
 
It isn`t. I noticed that it happened and was curious as to the
explanation.

That's cool. I do this as well, but sometimes I have to wonder as many
times people get the problem and the problem plus attempted solution mixed
up. Better to ask intent than assume and try to answer. ;-)

Peace and Grace,

--
Gregory A. Beamer (MVP)

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

*******************************************
| Think outside the box! |
*******************************************
 
wannabe said:
Am I being misled? Why is there a GC.Collect() method if there is supposedly
no way to control the GC?

Because, very rarely, it is useful to tell the GC to do a collection.
Most applications never need to, nor should, call the method.
I figure that GC.Collect() will collect all garbage
and that regular calls to it will dispose every unused object, even
IDisposables.

Garbage collection is _not_ the same as disposing.

Disposing exists only because .NET has to interact with systems on the
computer that are unmanaged, and thus has no way to know how to release
those unmanaged resources. A disposable object will get _in the way of_
a collection operation if it hasn't been properly managed by the user's
code, because it causes the object to wind up in the finalizer queue
rather than actually getting collected.

Dispose your IDisposables. Let the GC do its job when it wants to.
These are probably two of the most important rules with respect to
managed code and its memory model.

Pete
 
Peter Duniho said:
mick said:
[...]
Just for clarity then (for me) Do I need
to Dispose of this oject myself or does the GC do it for me? I also remember
watching one of those MSN Webcast series which, again, I`m almost certain
said that if you`re not sure which objects you should dispose of yourself
then check to see if it exposes the Dispose method.

What you should check for is IDisposable. For example:

object someObject = ...;

later:

IDisposable disposable = someObject as IDisposable;

if (disposable != null)
{
disposable.Dispose();
}

How exactly that code will look depends a lot on the lifetime of the
object. If it's used only locally, then a "using" statement is best.
Otherwise, you need to track the lifetime of the object in some sensible
way, and make sure you call Dispose() before you lose track of the object.

Note that in many cases, you know the exact type of the object, and thus
already know whether it implements IDisposable or not, and thus can just
go ahead and call Dispose() directly, without checking for the
implementation (for some objects – those that implement IDisposable
explicitly rather than implicitly – you'll have to cast them to
IDisposable to access the Dispose() method).

In any case, the phrase "when you are finished with it" hides a lot of
potential complexity. In the SoundPlayer example, it's reasonable to
assume that you might want to pre-load a sound, and then keep that
pre-loaded SoundPlayer instance around so that you can play the sound
any time you like. In that case, you wouldn't dispose the instance
until you are sure you won't need to play that sound again. That might
actually be when your program is shutting down!

In any case, yes…you should always dispose your objects somehow. And
that's true even if you happen to find out that for a particular object,
the Dispose() method turns out to be a NOP. You never know when the
object implementation might change. If it implements IDisposable,
that's its way of telling you that you do need to dispose it when you're
finally through with it.

Properly implemented IDisposable objects will also have a finalizer,
which will allow the GC to dispose the object for you if you should
happen to forget _and_ the object becomes unreachable (i.e.
collectable). But you shouldn't rely on that; it's a backstop for the
object, not for your own code to depend on. Garbage collection and
object finalization happens on a non-deterministic basis; even if the
object does get finalized, it's less efficient to let the GC finalize
objects than to dispose them explicitly. And there is actually no
guarantee the GC will ever actually dispose and collect your object.

I managed to miss this reply somehow. Thanks for the excellent explanation.

mick
 
Back
Top