我想了解如何基于头值应用SemaphoreSlim(或amy其他用于并发的locker)。
比方说,我有一个多个客户端使用的应用程序,我想将一些方法限制为每个客户端只能调用一个。
我的主代码如下所示:
private readonly SemaphoreSlim semaphore;
public class(SemaphoreSlim semaphore)
{
this.semaphore = semaphore;
}
public async Task SomeMethodAsync()
{
await this semaphore.WaitAsync()
try
{
// await some async stuff
}
finally
{
semaphore.Release();
}
}
我试图在Program.cs上注入SemaphoreSlim,比如
private static readonly ConcurrentDictionary<string, SemaphoreSlim> semaphores = new ();
internal static IServiceCollection ConfigureSemaphore(this IServiceCollection services)
{
return services.AddScoped(provider =>
{
IHttpContextAccessor context = provider.GetRequiredService<IHttpContextAccessor>();
string? clientId = (context.HttpContext?.Request.Headers["clientId"])?.ToString();
return semaphores.GetOrAdd(clientId ?? "0", _ => new SemaphoreSlim(1));
});
}
这样,我就知道每个客户端都会有自己的基于clientId头的信号量。
对我来说很有道理,但我确信我遗漏了一些东西,因为当我启动API时,第一个调用有效,但下一个具有相同clientId头的调用抛出异常,表明SemaphoreSlim已被释放。
我知道需要对注入进行Scoped,因为我需要检查每个请求的头值,但当将其切换到Singleton时,Semaphore实例不会在第一次调用结束时被处理。这不会起作用,因为Singleton注入会为任何clientId注入相同的Semaphore,这不是我们的想法。
So... What should I do to avoid the SemaphoreSlim being disposed? Or... What would be the correct approach to limit the concurrency by client?
(我检查了lock关键字,但它不适用于异步调用)