在 C# 中,我正在调用公共 API,该 API 的 API 限制为每秒 10 次调用。
API有多种方法,不同的用户可以调用不同的方法
一次,因此有可能出现“已达到速率限制”异常。
我有以下类结构:
public class MyServiceManager
{
public int Method1()
{
}
public void Method2()
{
}
public string Method3()
{
}
}
多个用户可以一次调用不同的方法,我如何维护静态调用队列或
任务使我可以监控所有请求并在一秒钟内仅处理 10 个请求
您可以基于以下内容构建一个 TaskLimiterSemaphoreSlim https://msdn.microsoft.com/library/system.threading.semaphoreslim(v=vs.110).aspx
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;
}
}
It will
- 等待信号量“槽”
- 开始真正的任务
- 当实际任务完成时,在给定的时间跨度后释放信号量槽
这是一个示例用法
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);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)