I'm trying to write a drop-in replacement for System.Media.SoundPlayer
using the waveOut...
API. This API makes a callback to a method in my version of SoundPlayer when the file/stream passed it has completed playback.
If I create a form-scoped instance of my SoundPlayer and play something, everything works fine because the form keeps the object alive, so the delegate is alive to receive the callback.
If I use it like this in, say, a button click event:
SoundPlayer player = new SoundPlayer(@"C:\whatever.wav");
player.Play();
... it works fine 99% of the time, but occasionally (and frequently if the file is long) the SoundPlayer object is garbage-collected before the file completes, so the delegate is no longer there to receive the callback, and I get an ugly error.
I know how to "pin" objects using GCHandle.Alloc
, but only when something else can hang onto the handle. Is there any way for an object to pin itself internally, and then un-pin itself after a period of time (or completion of playback)? If I try GCHandle.Alloc (this, GCHandleType.Pinned);
, I get a run-time exception "Object contains non-primitive or non-blittable data."