'How do I schedule work on the ThreadPool without causing thread starvation
I am consuming messages from a queue, and want to invoke a message handler such that I am processing messages as fast as possible. The message handler is asynchronous, but also does some CPU work.
I have considered the following approaches:
- On each message call Task.Run
foreach (var workItem in GetWorkItemsFromQueue())
{
Task.Run(workItem);
}
- Same as 1, but try and not exhaust the ThreadPool
foreach (var workItem in GetWorkItemsFromQueue())
{
while (ThreadPool.PendingWorkItemCount > 10)
{
await Task.Delay(1);
}
Task.Run(workItem);
}
- Use Parallel.ForEachAsync with 'unbounded' concurrency. Initially i was using -1 as per the docs, but changed this to int.MaxValue based on comments below
var options = new ParallelOptions
{
MaxDegreeOfParallelism = int.MaxValue
};
await Parallel.ForEachAsync(GetWorkItemsFromQueue(), options, async (workItem, token) =>
{
await workItem();
});
- Same as above, but with the default MaxDegreeOfParallelism (i.e. Environment.ProcessorCount)
await Parallel.ForEachAsync(GetWorkItemsFromQueue(), async (workItem, token) =>
{
await workItem();
});
- Use LongRunning Threads. Admittedly this isn't actually using the ThreadPool
foreach (var workItem in GetWorkItemsFromQueue())
{
Task.Factory.StartNew(() => workItem().GetAwaiter().GetResult(),
TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness | TaskCreationOptions.DenyChildAttach);
}
return Task.CompletedTask;
The most obvious approach would seem to be simply calling Task.Run(...) but with this approach I notice the ThreadPool.PendingWorkItemCount quickly growing.
Ideally I would like the ThreadPool queue to act like a BlockingCollection of capacity 1, which is what example 2 is trying to achieve.
Ultimately I feel like this must be a solved problem, but I'm struggling to find the solution, so I'm hoping someone can point me in the right direction.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
