PC Review


Reply
Thread Tools Rate Thread

Thread Synchronisation

 
 
Steven Spencer \(Spinalogic\)
Guest
Posts: n/a
 
      18th Feb 2007
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.

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




 
Reply With Quote
 
 
 
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      18th Feb 2007
Steven Spencer (Spinalogic) <Spence-(E-Mail Removed)> 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 - <(E-Mail Removed)>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
Steven Spencer \(Spinalogic\)
Guest
Posts: n/a
 
      18th Feb 2007
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.


"Jon Skeet [C# MVP]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Steven Spencer (Spinalogic) <Spence-(E-Mail Removed)> 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 - <(E-Mail Removed)>
> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
> If replying to the group, please do not mail me too



 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      18th Feb 2007
Steven Spencer (Spinalogic) <Spence-(E-Mail Removed)> wrote:
> 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.


Then Monitor.Wait/Pulse should be fine.

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
mangist@gmail.com
Guest
Posts: n/a
 
      23rd Feb 2007
On Feb 18, 3:35 am, "Steven Spencer \(Spinalogic\)" <Spence-
Spinalo...@newsgroup.nospam> wrote:
> 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.
>
> "Jon Skeet [C# MVP]" <s...@pobox.com> wrote inmessagenews:(E-Mail Removed)...
>
>
>
> > 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 -


I would recommend using an AutoResetEvent to signal to the thread that
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.

 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      25th Feb 2007
<(E-Mail Removed)> wrote:

<snip>

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


In what way would you say they're better than using Monitor.Wait/Pulse?
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 - <(E-Mail Removed)>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ShowDialog - Cross-thread operation not valid: Control'CheckAccountInfo' accessed from a thread other than the thread it was createdon. Tom C Microsoft C# .NET 9 20th Feb 2008 09:15 PM
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on Joe Microsoft C# .NET 4 12th Mar 2007 10:59 AM
Thread Synchronisation question =?Utf-8?B?TmF2ZWVuIE11a2tlbGxp?= Microsoft C# .NET 3 9th Feb 2005 07:00 PM
Thread A calls a delegate on Thread B but Thread A executes it!?!? Paul Tomlinson Microsoft C# .NET 4 3rd Feb 2005 11:09 PM
Synchronisation hangs during save of synchronisation log. Dirk Microsoft Outlook 0 10th Feb 2004 08:46 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 08:18 AM.