Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum queued elements in ThreadPool.QueueUserWorkItem

I set the max thread to 10. Then I added 22000 task using ThreadPool.QueueUserWorkItem. It is very likely that not all the 22000 task was completed after running the program. Is there a limitation how many task can be queued for avaiable threads?

like image 734
Andras Csehi Avatar asked Jan 19 '10 18:01

Andras Csehi


People also ask

How do you wait for ThreadPool to finish?

You can wait for a task to finish in a ThreadPoolExecutor by calling the wait() module function.

What is ThreadPool QueueUserWorkItem?

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

Does Task run Use the ThreadPool?

By default, TPL types like Task and Task<TResult> use thread pool threads to run tasks. You can also use the thread pool by calling ThreadPool.

What is ThreadPool in C#?

Thread pool in C# is a collection of threads. It is used to perform tasks in the background. When a thread completes a task, it is sent to the queue wherein all the waiting threads are present. This is done so that it can be reused. Let us see how to create a thread pool.


1 Answers

If you need to wait for all of the tasks to process, you need to handle that yourself. The ThreadPool threads are all background threads, and will not keep the application alive.

This is a relatively clean way to handle this type of situation:

 using (var mre = new ManualResetEvent(false))
 {
      int remainingToProcess = workItems.Count(); // Assuming workItems is a collection of "tasks"
      foreach(var item in workItems)
      {
           // Delegate closure (in C# 4 and earlier) below will 
           // capture a reference to 'item', resulting in
           // the incorrect item sent to ProcessTask each iteration.  Use a local copy
           // of the 'item' variable instead.
           // C# 5/VS2012 will not require the local here.
           var localItem = item;
           ThreadPool.QueueUserWorkItem(delegate
           {
               // Replace this with your "work"
               ProcessTask(localItem);

               // This will (safely) decrement the remaining count, and allow the main thread to continue when we're done
               if (Interlocked.Decrement(ref remainingToProcess) == 0)
                      mre.Set();
           });
      }
      mre.WaitOne();
 }

That being said, it's usually better to "group" together your work items if you have thousands of them, and not treat them as separate Work Items for the threadpool. This is some overhead involved in managing the list of items, and since you won't be able to process 22000 at a time, you're better off grouping these into blocks. Having single work items each process 50 or so will probably help your overall throughput quite a bit...

like image 56
Reed Copsey Avatar answered Oct 13 '22 22:10

Reed Copsey