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."