views:

251

answers:

7

Hello,

I'm new to threading and want to do something similar to this question:

http://stackoverflow.com/questions/100291/speed-up-loop-using-multithreading-in-c-question

However, I'm not sure if that solution is the best one for me as I want them to keep running and never finish. (I'm also using .net 3.5 rather than 2.0 as for that question.)

I want to do something like this:

foreach (Agent agent in AgentList)
{
    // I want to start a new thread for each of these
    agent.DoProcessLoop();
}

---

public void DoProcessLoop()
{
    while (true)
    {
        // do the processing

        // this is things like check folder for new files, update database
        // if new files found
    }
}

Would a ThreadPool be the best solution or is there something that suits this better?

Update: Thanks for all the great answers! I thought I'd explain the use case in more detail. A number of agents can upload files to a folder. Each agent has their own folder which they can upload assets to (csv files, images, pdfs). Our service (it's meant to be a windows service running on the server they upload their assets to, rest assured I'll be coming back with questions about windows services sometime soon :)) will keep checking every agent's folder if any new assets are there, and if there are, the database will be updated and for some of them static html pages created. As it could take a while for them to upload everything and we want them to be able to see their uploaded changes pretty much straight away, we thought a thread per agent would be a good idea as no agent then needs to wait for someone else to finish (and we have multiple processors so wanted to use their full capacity). Hope this explains it!

Thanks,

Annelie

+2  A: 

One issue with ThreadPool would be that if the pool happens to be smaller than the number of Agents you would like to have, the ones you try to start later may never execute. Some tasks may never begin to execute, and you could starve everything else in your app domain that uses the thread pool as well. You're probably better off not going down that route.

Eric Mickelsen
@tehMick Interesting point! Do you have any suggestions as to what to do instead? The reason we wanted to do threading was that we don't want anyone who's uploading stuff to have to wait too long, and as we have multiple processors then we'd use their full capacity.
annelie
If you're monitoring a file system, I would definitely do that on a single thread since multiple threads would just fight over file access. Then each file you find can be queued as a work item for the thread pool to pick up. But there are a number of other valid ways to approach it.
Eric Mickelsen
Though, thinking about it more, I could be misunderstanding the use case here, I'm not completely clear on the context.
Eric Mickelsen
A: 

Until you upgrade to .NET 4, the ThreadPool might be your best option. You may also want to use a Semaphore and a AutoResetEvent to control the number of concurrent threads. If you're talking about long-running work then the overhead of starting up and managing your own threads is low and the solution is more elegant. That will allow you to use a WorkerThread.Join() so you can make sure all worker threads are complete before you resume execution.

Nate Zaugg
I assume the while (true) is only psuedocode.
Nate Zaugg
+1  A: 

A thread pool is useful when you expect threads to be coming into and out of existence fairly regularly, not for a predefined set number of threads.

Tejs
@Tejs Yep, I see your point. Any suggestions for what to do instead? (see my previous comment for why we went for this)
annelie
I'd never implement a while(true) loop - that's unterminatable unless you want to throw an exception, or just kill the thread. If you need to have concurrency, consider just do something like this:<pre> Thread x = new Thread(new ThreadStart(Foo)); x.Start(); // If Some conditions change later, and you want to kill it, call x.Abort() public void Foo() { // Do Stuff }</pre>
Tejs
+2  A: 

You definitely don't want to use the ThreadPool for this purpose. ThreadPool threads are not meant to be used for long-running tasks ("infinite" counts as long-running), since that would obviously tie up resources meant to be shared.

For your application, it would probably be better to create one thread (not from the ThreadPool) and in that thread execute your while loop, inside of which you iterate through your Agents collection and perform the processing for each one. In the while loop you should also use a Thread.Sleep call so you don't max out the processor (there are better ways of executing code periodically, but Thread.Sleep will work for your purposes).

Finally, you need to include some way for the while loop to exit when your program terminates.

Update: Finally finally, multi-threading does not automatically speed up slow-running code. Nine women can't make a baby in one month.

MusiGenesis
But an octo-mom can make one baby per month... :-P
Eric Mickelsen
Although threading usually DOES speed up processing time, especially in these many-core processors of modern desktop and server machines. So long is there is not a single resource that each thread needs they will execute faster even on a single core machine. Also, the ThreadPool is meant to be used! I really don't think they mean while (true) other than for the purposes of psudocode.
Nate Zaugg
@Nate: the OQ said "I want them to keep running and never finish", which I took to mean that they meant `while (true)` quite literally. Of course the ThreadPool is meant to be used - just not in this way.
MusiGenesis
+4  A: 

I believe that the Parallels Extensions make this possible:

Parallel.Foreach

http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.foreach.aspx http://blogs.msdn.com/pfxteam/

Frederik Gheysels
+12  A: 

Given the specific usage your describe (watching for files), I'd suggest you use a FileSystemWatcher to determine when there are new files and then fire off a thread with the threadpool to process the files until there are no more to process -- at which point the thread exits.

This should reduce i/o (since you're not constantly polling the disk), reduce CPU usage (since the constant looping of multiple threads polling the disk would use cycles), and reduce the number of threads you have running at any one time (assuming there aren't constant modifications being made to the file system).

You might want to open and read the files only on the main thread and pass the data to the worker threads (if possible), to limit i/o to a single thread.

Ragoczy
Was just about to post this myself.
Daniel Schaffer
Definitely a saner approach.
Eric Mickelsen
This is the right approach. Your FileSystemWatcher event handler should post new files to a queue, which is watched by a separate supervisor thread that spawns separate worker threads to ingest the files. This lets you control the number of worker threads and minimize the chance of a FileSystemWatcher buffer overflow.Each worker thread should continually test until it gets exclusive access to its file so that you don't start reading until the file's writer is finished.
ebpower
Thanks, I'll give this a go!
annelie
A: 

Hmm.. as Ragoczy points out, its better to use FileSystemWatcher to monitor the files. However, since you have additional operations, you may think in terms of multithreading.

But beware, no matter how many processers you have, there is a limit to it's capacity. You may not want to create as many threads as the number of concurrent users, for the simple reason that your number of agents can increase.

Srikanth Venugopalan