c# - SoundPlayer.Stop does not stop sound playback -


i have application written in c# plays little .wav files. uses soundplayer class in system.media namepace play sounds, using thread calls soundplayer.playsync method play .wav file. it's wrapped in class looks this:

public class soundcontroller {      private object soundlocker = new object();      protected thread soundthread { get; set; }      protected string nextsound { get; set; }      protected autoresetevent playasoundplag { get; set; }      protected dictionary<string, soundplayer> sounds { get; set; }      protected bool stopping { get; set; }      public string soundplaying { get; private set; }       public soundcontroller() {         pendingcount = 0;         playasoundflag = new autoresetevent( false );         sounds = new dictionary<string, soundplayer>();         soundlocker = new object();         stopping = false;         soundthread = new thread( new threadstart( soundplayer ) ) { name = "soundthread", isbackground = true };         soundthread.start();     }      private void soundplayer() {         {             playasoundflag.waitone();              bool soundwasplayed = false;              while ( !stopping && nextsound != null ) {                 lock ( soundlocker ) {                     soundplaying = nextsound;                     nextsound = null;                 }                 sounds[ soundplaying ].playsync();                 lock ( soundlocker ) {                     soundplaying = null;                     soundwasplayed = true;                 }             }         } while ( !stopping );     }      public bool hassound( string key ) {         return sounds.containskey( key );     }      public void playalarmsound( string key, bool stopcurrentsound ) {         if ( !sounds.containskey( key ) )             throw new argumentexception( "sound unknown", "key" );          lock ( soundlocker ) {             nextsound = key;              if ( soundplaying != null && stopcurrentsound )                 sounds[ soundplaying ].stop();              playasoundflag.set();         }     } } 

when program calls playsound method, , sound playing, stop method called, sound that's playing doesn't stop. i've placed trace points on call stop , line added after see when call made , when returned, while listening headphones. it's obvious sound plays way through end.

how sounds stop playing reliably?

unfortunately messy process, works:

 class program     {         static void main(string[] args)         {             soundplayerex player = new soundplayerex(@"c:\temp\sorry_dave.wav");             player.soundfinished += player_soundfinished;              console.writeline("press key play sound");             console.readkey(true);             player.playasync();              console.writeline("press key stop sound.");             console.readkey(true);             player.stop();              console.writeline("press key continue");         }          static void player_soundfinished(object sender, eventargs e)         {             console.writeline("the sound finished playing");         }     }      public static class soundinfo     {         [dllimport("winmm.dll")]         private static extern uint mcisendstring(             string command,             stringbuilder returnvalue,             int returnlength,             intptr winhandle);          public static int getsoundlength(string filename)         {             stringbuilder lengthbuf = new stringbuilder(32);              mcisendstring(string.format("open \"{0}\" type waveaudio alias wave", filename), null, 0, intptr.zero);             mcisendstring("status wave length", lengthbuf, lengthbuf.capacity, intptr.zero);             mcisendstring("close wave", null, 0, intptr.zero);              int length = 0;             int.tryparse(lengthbuf.tostring(), out length);              return length;         }     }      public class soundplayerex : soundplayer     {         public bool finished { get; private set; }          private task _playtask;         private cancellationtokensource _tokensource = new cancellationtokensource();         private cancellationtoken _ct;         private string _filename;         private bool _playingasync = false;          public event eventhandler soundfinished;          public soundplayerex(string soundlocation)             : base(soundlocation)         {             _filename = soundlocation;             _ct = _tokensource.token;         }          public void playasync()         {             finished = false;             _playingasync = true;             task.run(() =>             {                 try                 {                     double lenms = soundinfo.getsoundlength(_filename);                     datetime stopat = datetime.now.addmilliseconds(lenms);                     this.play();                     while (datetime.now < stopat)                     {                         _ct.throwifcancellationrequested();                         //the delay helps reduce processor usage while "spinning"                         task.delay(10).wait();                     }                 }                 catch (operationcanceledexception)                 {                     base.stop();                 }                                 {                     onsoundfinished();                 }              }, _ct);                     }          public new void stop()         {             if (_playingasync)                 _tokensource.cancel();             else                 base.stop();   //to stop soundplayer wave file         }          protected virtual void onsoundfinished()         {             finished = true;             _playingasync = false;              eventhandler handler = soundfinished;              if (handler != null)                 handler(this, eventargs.empty);         }     } 

so why doesn't work "normally"? known problem. soundplayer "fire , forget" piece of code, , if don't cancel on same thread started on, not anything. lot of people complain , i'm sure you've seen there few solutions out side of using raw wave_out calls or moving directx (or wpf, using mediaplayer control).

this soundplayerex class has couple properties let know when sound finished or cancel playing sound started asynchronously. there no need create new thread work on, making lot easier use.

feel free expand on code, quick , dirty solution problem. 2 classes need soundinfo class , soundplayerex class, rest of code above demo (replace wav file 1 of own).

note not universal solution relies on winmm.dll, not port on mono (not sure if mono has soundplayer class or not). since dirty solution, won't finished event or property if don't use playasync call.