|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Thread Synchronisationcompiler has warned me of some deprecated usage of functions :(. Namely thread.suspend and thread.resume. My class was quite clean and the logic was sound (ie it worked). Now I was considering writing the main loop to grab a semaphore whilst executing and then play a file, however, I wish to have no limit on the number of sounds that can be queued up by the player, so I can't use a semaphore as I cannot know how many sounds can enqueue at any one time, and I CANNOT have the main thread block in its call to "playsound" as would happen if I attempted to "release" whilst the semaphore was already held. I was considering using a monitor but then I run into the double check problem, I need to check the monitor is released at just the right time and all sorts of issues happen. I suppose if someone could point me in the right direction for a good technique to use. Essentially the class needs to return from playsound immediately after enqueuing the file name. The main thread should wake up any time that a sound is added to the queue, dequeue the sound and then play it. Order and Timing are important (ie sounds must be played in the order they are received, and all sounds in the queue MUST be played without a delay (ie, Attention, "name", "Message" would be a common usage of the function). I just can't think of a construct that would work efficiently. And I'm certainly not asking people to write code for me, but if you can point in the right direction I'd really appreciate it. My CURRENT class is listed below. Public Class AsyncSounds Implements IDisposable Private PlayQueue As System.Collections.Queue Private SoundThread As System.Threading.Thread Private Exiting As Boolean = False Public Sub New() PlayQueue = New System.Collections.Queue SoundThread = New System.Threading.Thread(AddressOf PlayThread) SoundThread.Name = "Sound Playing Thread" SoundThread.Start() Console.WriteLine("Sound Thread: Starting the Sound Play Thread") End Sub Public Sub PlaySound(ByVal SoundFile As String) SyncLock (PlayQueue) PlayQueue.Enqueue(SoundFile) End SyncLock Console.WriteLine("Main Thread: Added sound to queue.") If SoundThread.ThreadState = Threading.ThreadState.Suspended Then SoundThread.Resume() ''If the player is asleep, wake it up. End If End Sub Private Sub PlayThread() Dim Count As Integer = 0 Dim SoundFile As String = String.Empty Do If Exiting Then Console.WriteLine("Sound Thread: Terminating") Exit Sub End If SyncLock (PlayQueue) Count = PlayQueue.Count End SyncLock If Count > 0 Then SyncLock (PlayQueue) SoundFile = CType(PlayQueue.Dequeue, String) End SyncLock Console.WriteLine("Sound Thread: Playing Sound. Count = " & Count.ToString) SoundClass.PlaySoundFile(SoundFile, True) Else Console.WriteLine("Sound Thread: Suspending") System.Threading.Thread.CurrentThread.Suspend() End If Loop End Sub Public Sub Dispose() Implements System.IDisposable.Dispose If Not Exiting Then Exiting = True If SoundThread.ThreadState <> Threading.ThreadState.Running Then SoundThread.Resume() SoundThread.Join() GC.SuppressFinalize(Me) End If End Sub End Class Steven Spencer (Spinalogic) <Spence-Spinalogic@newsgroup.nospam> wrote:
Show quote > Hey everyone, just converted a class from .net 1.1 to .net 2.0 and the It's not clear to me why you're suspending and resuming at all, but > compiler has warned me of some deprecated usage of functions :(. Namely > thread.suspend and thread.resume. > > My class was quite clean and the logic was sound (ie it worked). Now I was > considering writing the main loop to grab a semaphore whilst executing and > then play a file, however, I wish to have no limit on the number of sounds > that can be queued up by the player, so I can't use a semaphore as I cannot > know how many sounds can enqueue at any one time, and I CANNOT have the main > thread block in its call to "playsound" as would happen if I attempted to > "release" whilst the semaphore was already held. > > I was considering using a monitor but then I run into the double check > problem, I need to check the monitor is released at just the right time and > all sorts of issues happen. Monitor.Wait/Pulse or Auto/ManualResetEvents are almost certainly the best solution here. See http://pobox.com/~skeet/csharp/threads/ for more information. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too I need the sounds to be enqueued in an Asynchronous manner.
I need the sounds to PLAY in a synchronous manner (1 followed by the next, as opposed to over the top of each other) I want the thread to sleep/block so that I'm not using a busy wait algorithm and hence being extremely inefficient. Show quote "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MPG.204217de4ae4f38298d89e@msnews.microsoft.com... > Steven Spencer (Spinalogic) <Spence-Spinalogic@newsgroup.nospam> wrote: >> Hey everyone, just converted a class from .net 1.1 to .net 2.0 and the >> compiler has warned me of some deprecated usage of functions :(. Namely >> thread.suspend and thread.resume. >> >> My class was quite clean and the logic was sound (ie it worked). Now I >> was >> considering writing the main loop to grab a semaphore whilst executing >> and >> then play a file, however, I wish to have no limit on the number of >> sounds >> that can be queued up by the player, so I can't use a semaphore as I >> cannot >> know how many sounds can enqueue at any one time, and I CANNOT have the >> main >> thread block in its call to "playsound" as would happen if I attempted to >> "release" whilst the semaphore was already held. >> >> I was considering using a monitor but then I run into the double check >> problem, I need to check the monitor is released at just the right time >> and >> all sorts of issues happen. > > It's not clear to me why you're suspending and resuming at all, but > Monitor.Wait/Pulse or Auto/ManualResetEvents are almost certainly the > best solution here. > > See http://pobox.com/~skeet/csharp/threads/ for more information. > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too Steven Spencer (Spinalogic) <Spence-Spinalogic@newsgroup.nospam> wrote:
> I need the sounds to be enqueued in an Asynchronous manner. Then Monitor.Wait/Pulse should be fine.> > I need the sounds to PLAY in a synchronous manner (1 followed by the next, > as opposed to over the top of each other) > > I want the thread to sleep/block so that I'm not using a busy wait algorithm > and hence being extremely inefficient. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too On Feb 18, 3:35 am, "Steven Spencer \(Spinalogic\)" <Spence-
Spinalo...@newsgroup.nospam> wrote: Show quote > I need the sounds to be enqueued in an Asynchronous manner. I would recommend using an AutoResetEvent to signal to the thread that> > I need the sounds to PLAY in a synchronous manner (1 followed by the next, > as opposed to over the top of each other) > > I want the thread to sleep/block so that I'm not using a busy wait algorithm > and hence being extremely inefficient. > > "Jon Skeet [C# MVP]" <s***@pobox.com> wrote inmessagenews:MPG.204217de4ae4f38298d***@msnews.microsoft.com... > > > > > Steven Spencer (Spinalogic) <Spence-Spinalo...@newsgroup.nospam> wrote: > >> Hey everyone, just converted a class from .net 1.1 to .net 2.0 and the > >> compiler has warned me of some deprecated usage of functions :(. Namely > >> thread.suspend and thread.resume. > > >> My class was quite clean and the logic was sound (ie it worked). Now I > >> was > >> considering writing the mainloopto grab a semaphore whilst executing > >> and > >> then play a file, however, I wish to have no limit on the number of > >> sounds > >> that can be queued up by the player, so I can't use a semaphore as I > >> cannot > >> know how many sounds can enqueue at any one time, and I CANNOT have the > >> main > >> thread block in its call to "playsound" as would happen if I attempted to > >> "release" whilst the semaphore was already held. > > >> I was considering using a monitor but then I run into the double check > >> problem, I need to check the monitor is released at just the right time > >> and > >> all sorts of issues happen. > > > It's not clear to me why you're suspending and resuming at all, but > > Monitor.Wait/Pulse or Auto/ManualResetEvents are almost certainly the > > best solution here. > > > Seehttp://pobox.com/~skeet/csharp/threads/for more information. > > > -- > > Jon Skeet - <s***@pobox.com> > >http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet > > If replying to the group, please do not mail me too- Hide quoted text - > > - Show quoted text - a sound has finished and to play the next one. I.e. (In C# I apologize) using System.Threading; private Queue soundQueue = new Queue(); // This is our wait handle for signalling the thread private AutoResetEvent waitHandle = new AutoResetEvent(false); private bool running = false; public void PlaySound(string soundFile) { lock (soundQueue) { soundQueue.Enqueue(soundFile) // Now you want to signal to the soundThread that a new sound was added waitHandle.Set(); } } public void New() { running = true; Thread soundThread = new Thread(new ThreadStart (PlayThread)); soundThread.Start(); } public void PlayThread() { do { lock (soundQueue) { if (soundQueue.Count > 0) { // Play the sound.... } } } while (running && waitHandle.WaitOne()); } public void StopThread() { running = false; // Signal the thread that we have changed the status of running waitHandle.Set(); } There you have it, runs like a charm. AutoResetEvents and ManualResetEvents are the best way of signalling to another thread that you want it to continue processing. Waiting on a resetEvent will block the thread until you signal (i.e. Set()) the wait handle. <mang***@gmail.com> wrote:
<snip> > There you have it, runs like a charm. AutoResetEvents and In what way would you say they're better than using Monitor.Wait/Pulse? > ManualResetEvents are the best way of signalling to another thread > that you want it to continue processing. Waiting on a resetEvent will > block the thread until you signal (i.e. Set()) the wait handle. There are certainly situations where they're more applicable, particularly where you want to be able to wait on multiple handles, but my "default choice" is usually to use monitors, which are "lighter weight" than Manual/AutoResetEvents. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too |
|||||||||||||||||||||||