Using SemaphoreSlim to limit concurrent API calls

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;


class Program
{
    // Semaphore to limit concurrent calls
    private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(5); // Maximum 5 concurrent calls


    static async Task Main(string[] args)
    {
        string apiUrl = "https://api.example.com/endpoint";


        // Simulate multiple API calls
        var tasks = new Task[20]; // Simulate 20 API requests


        for (int i = 0; i < tasks.Length; i++)
        {
            int requestId = i + 1; // Capture the request ID
            tasks[i] = MakeApiCallAsync(apiUrl, requestId);
        }


        // Wait for all tasks to complete
        await Task.WhenAll(tasks);


        Console.WriteLine("All API calls completed.");
    }


    private static async Task MakeApiCallAsync(string apiUrl, int requestId)
    {
        await Semaphore.WaitAsync(); // Wait for a slot to be available


        try
        {
            using (HttpClient client = new HttpClient())
            {
                Console.WriteLine($"Request {requestId}: Started.");
                HttpResponseMessage response = await client.GetAsync(apiUrl);


                Console.WriteLine($"Request {requestId}: Completed with status {response.StatusCode}.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Request {requestId}: Error - {ex.Message}");
        }
        finally
        {
            Semaphore.Release(); // Release the semaphore slot
        }
    }
}