Home > Software design >  Throttling threads in C#
Throttling threads in C#

Time:12-05

I have a situation where I am doing WebAPI calls to a service which sometimes cannot keep up with the load. I'm keeping track of how long the WebAPI takes to respond and how many active threads I have, and when the WebAPI is taking long to respond I want to limit the number of concurrent calls to a specific number (which I'd save in a config).

What I was thinking was of using SemaphoreSlim but the problem would be that at that time the number of concurrent threads would most likely be greater than the number I'm limiting to. Is there a neat way of tackling this problem that wouldn't involve reinventing the wheel?

CodePudding user response:

I have created a library that does just that. It's called SemaphoreSlimThrottling and is available on GitHub and NuGet. Suppose you had 11 concurrent threads and wanted to limit them to 10. SemaphoreSlim doesn't allow you to initialize with an initialCount of -1 (i.e. you need to release 2 before a new one can enter), but with SemaphoreSlimThrottle you can.

var mySemaphore = new SemaphoreSlimThrottle(-1, 10);

CodePudding user response:

One way to solve this problem is to use a SemaphoreSlim object to limit the number of concurrent threads that can access a critical section of code. When a thread wants to enter the critical section, it can call the Wait() method on the SemaphoreSlim object. If the number of threads that are currently in the critical section is less than the maximum number allowed, the thread will be granted access to the critical section and the SemaphoreSlim's internal count will be decremented by 1. Otherwise, the thread will be blocked until another thread leaves the critical section and the SemaphoreSlim's count is incremented.

When a thread leaves the critical section, it should call the Release() method on the SemaphoreSlim object to increment the count and potentially unblock another thread that is waiting to enter the critical section.

Here is an example of how you could use a SemaphoreSlim object to limit the number of concurrent threads that can access a critical section of code:

// Create a SemaphoreSlim object with a maximum count of 10.
// This means that at most 10 threads can be in the critical section at the same time.
SemaphoreSlim semaphore = new SemaphoreSlim(10);

// This is the critical section of code that we want to limit access to.
void MakeWebApiCall()
{
    // Acquire a lock on the semaphore.
    // If the number of threads in the critical section is already at the maximum allowed,
    // this thread will be blocked until another thread leaves the critical section.
    semaphore.Wait();

    try
    {
        // Make the WebAPI call here.
        // Note that only 10 threads can be in this section of code at the same time.
    }
    finally
    {
        // Release the lock on the semaphore.
        // This will increment the semaphore's count and potentially unblock another thread
        // that is waiting to enter the critical section.
        semaphore.Release();
    }
}
  • Related