Although the code about which I will talk here I wrote in F#, it is based on the .NET 4 framework, not specifically depending on any particularity of F
Are you sure that your individual tasks are completing in a timely manner? I believe that both Parallel.ForEach
and the Task
class already use the .NET threadpool. Tasks should generally be short-lived work items, in which case the threadpool will only spawn a small number of actual threads, but if your tasks are not making progress and there are other tasks queued then the number of threads used will steadily increase up to the maximum (which by default is 250/processor in .NET 2.0 SP1, but is different under different versions of the framework). It's also worth noting that (at least in .NET 2.0 SP1) new thread creation is throttled to 2 new threads per second, so getting up to the number of threads you're seeing indicates that the tasks are not completing in a short amount of time (so it may not be completely accurate to pin the blame on Parallel.ForEach
).
I think that Brian's suggestion to use async
workflows is a good one, particularly if the source of the long-lived tasks is IO, since async
will return your threads to the threadpool until the IO completes. Another option is to simply accept that your tasks aren't completing quickly and allow the spawning of many threads (which can be controlled to some extent by using System.Threading.ThreadPool.SetMaxThreads
) - depending on your situation it may not be a big deal that you're using a lot of threads.
Using 'async's will enable you to do the I/O-bound work without burning threads while the various I/O calls are 'at sea', so that would be my first suggestion. It should be straightforward to convert the code to async, usually along the lines of
async{...}
, add return
where necessaryAsync.FromBeginEnd
let r = Foo()
to let! r = AsyncFoo()
Async.Parallel
to convert the 5000 async objects into a single Async that runs in parallelThere are various tutorials for doing this; one such webcast is here.
You could always use a ThreadPool
.
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx
basically:
QueueUserWorkItem(WaitCallback)
ParallelOptions.MaxDegreeOfParallelism limits the number of concurrent operations run by Parallel method calls