I have a List with items that I want to download. I use a for Loop to iterate the list.
For each item in this List I start a new Thread that references the item. My Problem is that I want limit the maxDownload at the same time.
for (int i = downloadList.Count - 1; i >= 0; i--)
{
downloadItem item = downloadList[i];
if (item.Status != 1 && item.Status != 2)
{
ThreadStart starter = delegate { this.DownloadItem(ref item); };
Thread t = new Thread(starter);
t.IsBackground = true;
t.Name = item.Name;
t.Priority = ThreadPriority.Normal;
t.Start();
}
}
I read something about the ThreadPool, but then I can't reference my item. Can someone Help me? Thanks! :)
Edit:
I tested this:
ThreadPool.SetMaxThreads(maxDownloads, maxDownloads);
ThreadPool.SetMinThreads(maxDownloads, maxDownloads);
ThreadPool.QueueUserWorkItem(DownloadItem, ref item);
I don't know how I can reference my downloadItem with this thread.....
I can't see why you are trying to use the
ref
keyword anyway. Objects are passed by reference in C# by default, and in your original code you are not usingitem
after it is passed toDownloadItem
. Therefore I would suggest using theThreadPool
methods you tried, but not using aref
parameter.Hope that helps.
if you're using .NET 4, I'd strongly suggest using Parallel.ForEach (potentially on downloadList.Reverse())
so, something like:
If you don't want the calling thread to block, you could QueueUserWorkItem this call, of course.
I solved this very problem in .Net 3.5 by creating threads and loading them into a queue. Then I read a thread from the queue, start it, and increment the running thread count. I keep doing this until I hit the upper limit.
As each thread finishes it invokes a callback method that decrements the running count and signals the queue reader to start more threads. For additional control you can use a dictionary to keep track of running threads, keyed by
ManagedThreadId
, so you can signal threads to stop early or report progress.Sample console app:
The best way to handle this is to only create
maxDownloads
number of threads. Put all of your work items into a queue and let the threads compete with each other to figure out which one processes each work item.You could also use a semaphore to throttle the number of threads processing work items. This is especially useful when the actual number of threads is unknown as would be the case if you were using the
ThreadPool
.I am not particularly fond of either approach. The problem with the first is that a nonfixed amount of threads are created. It is generally advised to avoid creating threads in a
for
loop as that tends to not scale well. The problem with the second is that the semaphore will block some of theThreadPool
threads. That is not advised either because you are effecitvely claiming one of threads and then doing nothing on it. That might effect the performance of other unrelated tasks that happen to be sharing theThreadPool
. I think in this case either of the two options will be fine since crafting a more scalable pattern is more work than it is worth.