I have an application I am writing that is using multiple threads to pull
down files from a web service. I want a thread to run for each file needed to
pull down. The code I have written works wonderfully. However, when I add in
the ability to control the number of threads running at any point in time to
be only 3 and then when one has finished another is started. So, if there are
15 files only 3 are being downloaded at the same time, when the first one has
finished another thread is started to get the next file. I then run into a
problem I am grappling with and need some help. The culprit is the while loop
in the code below:

for(int i=0; i<files.Length;i++)
{
while(threadsStarted >= maxThreads)
{
Thread.Sleep(50);
//hang tight for available thread to start
}

Interlocked.Increment(ref threadsStarted);


WorkerClass wc = new WorkerClass( this, showProgress, new object[] {
imsgs,files[i], decrementThreads } );
Thread t = new Thread( new ThreadStart(wc.RunProcess));
t.IsBackground = true; //make them a daemon - prevent thread callback
issues
t.Start();
EnableButton ( false );
}

When the threadsStarted reaches 3 it equals the maxThreads (which is set to
3 in code before this) then it is as if my threads stop running. I set a
break point in code that runs in the method the thread executes and it stops
at the point as long as threadsStarted variable is less than 3 but after that
it does not. So it seems like the while loop is suspending everything.

Any ideas how to correct this? I know I must be doing something wrong - I
just don't know what.

-Demetri

Re: Multi-Threading Problem by Jon

Jon
Sat Dec 04 13:11:20 CST 2004

Demetri <Demetri@discussions.microsoft.com> wrote:
> I have an application I am writing that is using multiple threads to pull
> down files from a web service. I want a thread to run for each file needed to
> pull down. The code I have written works wonderfully. However, when I add in
> the ability to control the number of threads running at any point in time to
> be only 3 and then when one has finished another is started. So, if there are
> 15 files only 3 are being downloaded at the same time, when the first one has
> finished another thread is started to get the next file. I then run into a
> problem I am grappling with and need some help. The culprit is the while loop
> in the code below:
>
> for(int i=0; i<files.Length;i++)
> {
> while(threadsStarted >= maxThreads)
> {
> Thread.Sleep(50);
> //hang tight for available thread to start
> }
>
> Interlocked.Increment(ref threadsStarted);
>
>
> WorkerClass wc = new WorkerClass( this, showProgress, new object[] {
> imsgs,files[i], decrementThreads } );
> Thread t = new Thread( new ThreadStart(wc.RunProcess));
> t.IsBackground = true; //make them a daemon - prevent thread callback
> issues
> t.Start();
> EnableButton ( false );
> }
>
> When the threadsStarted reaches 3 it equals the maxThreads (which is set to
> 3 in code before this) then it is as if my threads stop running. I set a
> break point in code that runs in the method the thread executes and it stops
> at the point as long as threadsStarted variable is less than 3 but after that
> it does not. So it seems like the while loop is suspending everything.
>
> Any ideas how to correct this? I know I must be doing something wrong - I
> just don't know what.

It looks like you're not getting threadsStarted and maxThreads in a
thread-safe way - see
http://www.pobox.com/~skeet/csharp/threads/volatility.shtml
for details.

I would suggest using a monitor and wait/pulse instead though, to tell
the thread when to run. There's no need to start a new thread each time
though - why not just start three threads and have a producer/consumer
type queue? (Alternatively, use a custom thread-pool with three threads
in.)

If you read through the article linked above (there are more pages than
just that one) you'll find details of all these approaches.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too