Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET ThreadPool QueueUserWorkItem Synchronization

I am employing ThreadPool.QueueUserWorkItem to play some sound files and not hanging up the GUI while doing so.

It is working but has an undesirable side effect.

While the QueueUserWorkItem CallBack Proc is being executed there is nothing to stop it from starting a new thread. This causes the samples in the threads to overlap.

How can I make it so that it waits for the already running thread to finish running and only then run the next request?

EDIT: private object sync = new Object(); lock (sync) { .......do sound here }

this works. plays in the sounds in order.

but some samples are getting played more than once when i keep sending sound requests before the one being played ends. will investigate.

EDIT: is the above a result of Lock Convoy @Aaronaught mentioned?

like image 872
iTEgg Avatar asked Mar 28 '10 18:03

iTEgg


People also ask

When should you not use ThreadPool?

Thread pools do not make sense when you need thread which perform entirely dissimilar and unrelated actions, which cannot be considered "jobs"; e.g., One thread for GUI event handling, another for backend processing. Thread pools also don't make sense when processing forms a pipeline.

What is the use of ThreadPool QueueUserWorkItem method in C#?

QueueUserWorkItem(WaitCallback, Object) Queues a method for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available.

What is .NET ThreadPool?

ThreadPool class provides your application with a pool of worker threads that are managed by the system, allowing you to concentrate on application tasks rather than thread management.

What happens when thread pool is full C#?

By default, the MaxThreads of the ThreadPool is very high. Usually you'll never get there, your app will crash first. So when all threads are busy the new tasks are queued and slowly, at most 1 per 500 ms, the TP will allocate new threads.


1 Answers

This is a classic thread synchronization issue, where you have multiple clients that all want to use the same resource and need to control how they access it. In this particular case, the sound system is willing to play more than one sound at the same time (and this is often desirable), but since you don't want that behavior, you can use standard locking to gate access to the sound system:

public static class SequentialSoundPlayer
{
    private static Object _soundLock = new object();

    public static void PlaySound(Sound sound)
    {
        ThreadPool.QueueUserWorkItem(AsyncPlaySound, sound);
    }

    private static void AsyncPlaySound(Object state)
    {
        lock (_soundLock)
        {
            Sound sound = (Sound) state;
            //Execute your sound playing here...
        }
    }
}

where Sound is whatever object you're using to represent a sound to be played. This mechanism is 'first come, first served' when multiple sounds vie for play time.


As mentioned in another response, be careful of excessive 'pile-up' of sounds, as you'll start to tie up the ThreadPool.

like image 145
Dan Bryant Avatar answered Nov 15 '22 19:11

Dan Bryant