在C#中,我调用的是一个公共API,它的API限制为每秒10次调用

在C#中,我调用的是一个公共API,它的API限制为每秒10次调用,c#,multithreading,task,task-parallel-library,C#,Multithreading,Task,Task Parallel Library,在C#中,我调用的是一个公共API,它的API限制为每秒10次调用。 API有多种方法,不同的用户可以随时调用不同的方法 一段时间后,可能会出现“达到利率限制”异常 我的班级结构如下: public class MyServiceManager { public int Method1() { } public void Method2() { } public string Method3() { } } 多个用户可

在C#中,我调用的是一个公共API,它的API限制为每秒10次调用。 API有多种方法,不同的用户可以随时调用不同的方法 一段时间后,可能会出现“达到利率限制”异常

我的班级结构如下:

public class MyServiceManager
{
    public int Method1()
    {
    }

    public void Method2()
    {
    }

    public string Method3()
    {
    }
}
多个用户可以一次调用不同的方法,如何维护静态调用队列或
任务,以便我可以监视所有请求,并在一秒钟内仅处理10个请求

您可以基于


您正在调用什么类型的数据?它是一个永远不会更改的静态数据列表,您可以缓存它吗?每秒10次调用是否只是自由访问其API的限制?可能重复。可能会有更好的副本,或者根本没有副本(因为这是关于速率限制,而不是任务数量本身)。您可以使用具有10个“插槽”的,并在一秒钟后释放每个“插槽”。这里存在一个结构性问题,如果您不能在消费者端应用任何速率限制,您可能会遇到大量等待的任务,可能足以让你最终耗尽资源。无论您使用的是任务、线程还是内部队列,这都是正确的。如果消费者是“理性的”,你可以让他们等待。你可能想看看这个限速器库——即使你推出自己的,看看其他人是如何实现它的也会很有用——这是一个极好的答案。它不仅提供了一个解决方案,您的答案还连接了我之前提出的几个不同的编码概念。谢谢你的贡献。
public class TaskLimiter
{
    private readonly TimeSpan _timespan;
    private readonly SemaphoreSlim _semaphore;

    public TaskLimiter(int count, TimeSpan timespan)
    {
        _semaphore = new SemaphoreSlim(count, count);
        _timespan = timespan;
    }

    public async Task LimitAsync(Func<Task> taskFactory)
    {
        await _semaphore.WaitAsync().ConfigureAwait(false);
        var task = taskFactory();
        task.ContinueWith(async e =>
        {
            await Task.Delay(_timespan);
            _semaphore.Release(1);
        });
        await task;
    }

    public async Task<T> LimitAsync<T>(Func<Task<T>> taskFactory)
    {
        await _semaphore.WaitAsync().ConfigureAwait(false);
        var task = taskFactory();
        task.ContinueWith(async e =>
        {
            await Task.Delay(_timespan);
            _semaphore.Release(1);
        });
        return await task;
    }
}
public class Program
{
    public static void Main()
    {
        RunAsync().Wait();
    }

    public static async Task RunAsync()
    {
        var limiter = new TaskLimiter(10, TimeSpan.FromSeconds(1));

        // create 100 tasks 
        var tasks = Enumerable.Range(1, 100)
           .Select(e => limiter.LimitAsync(() => DoSomeActionAsync(e)));
        // wait unitl all 100 tasks are completed
        await Task.WhenAll(tasks).ConfigureAwait(false);
    }

    static readonly Random _rng = new Random();

    public static async Task DoSomeActionAsync(int i)
    {
        await Task.Delay(150 + _rng.Next(150)).ConfigureAwait(false);
        Console.WriteLine("Completed Action {0}", i);
    }

}