C# lock语句块中的异步方法
我想在缓存中放置一个身份验证令牌,它可以在多个应用程序域中使用。此令牌将每小时过期一次。当客户端无法使用令牌进行授权时,它会要求令牌生成服务生成一个新的令牌 我只希望对第一个未成功进行身份验证的客户端执行此重新生成,因此我使用了如下锁定对象:C# lock语句块中的异步方法,c#,C#,我想在缓存中放置一个身份验证令牌,它可以在多个应用程序域中使用。此令牌将每小时过期一次。当客户端无法使用令牌进行授权时,它会要求令牌生成服务生成一个新的令牌 我只希望对第一个未成功进行身份验证的客户端执行此重新生成,因此我使用了如下锁定对象: public async Task<Token> GenerateToken(Token oldToken) { Token token; lock (lockObject) { var cachedTo
public async Task<Token> GenerateToken(Token oldToken)
{
Token token;
lock (lockObject)
{
var cachedToken = GetTokenFromCache();
if (cachedToken == oldToken)
{
var authClient = new AuthClient(id, key);
token = await authClient.AuthenticateClientAsync(); //KABOOM
PutTokenInCache(token);
}
else
{
token = cachedToken;
}
}
return token;
}
公共异步任务GenerateToken(令牌oldToken)
{
代币;
锁定(锁定对象)
{
var cachedToken=GetTokenFromCache();
if(cachedToken==oldToken)
{
var authClient=新的authClient(id,key);
令牌=等待authClient.AuthenticateClientAsync();//KABOOM
PuttokinCache(令牌);
}
其他的
{
令牌=缓存令牌;
}
}
返回令牌;
}
我的问题是
AuthClient
只有async
方法,并且在lock语句块中不允许使用async
方法。我无法控制AuthClient
,这里还有其他策略吗?您可以使用SemaphoreSlim
作为基本的异步就绪lock
替换:
private readonly SemaphoreSlim lockObject = new SemaphoreSlim(1);
public async Task<Token> GenerateToken(Token oldToken)
{
Token token;
await lockObject.WaitAsync();
try
{
var cachedToken = GetTokenFromCache();
if (cachedToken == oldToken)
{
var authClient = new AuthClient(id, key);
token = await authClient.AuthenticateClientAsync();
PutTokenInCache(token);
}
else
{
token = cachedToken;
}
}
finally
{
lockObject.Release();
}
return token;
}
private readonly信号量lim lockObject=新信号量lim(1);
公共异步任务GenerateToken(令牌oldToken)
{
代币;
wait lockObject.WaitAsync();
尝试
{
var cachedToken=GetTokenFromCache();
if(cachedToken==oldToken)
{
var authClient=新的authClient(id,key);
令牌=等待authClient.AuthenticateClientAsync();
PuttokinCache(令牌);
}
其他的
{
令牌=缓存令牌;
}
}
最后
{
lockObject.Release();
}
返回令牌;
}
您使用的是.NET 4.5还是.NET 4.5.1?有点。这看起来很棒!“SemaphoreSlim类表示一个轻量级、快速的信号量,当等待时间预计很短时,可用于在单个进程内等待。”如果检索令牌最多需要5秒,是否存在任何问题?@MisterEpic:否。但是,如果缓存在内存中,您可以考虑缓存任务而不是令牌,这将简化代码一点。“代码>锁语句的伟大之处在于它知道它是从哪个线程调用的,所以在<代码>锁< /代码>中的递归不是问题。code>SemaphoreSlim但是递归不兼容,所以它不是100%的替代品,请大家小心。@Alex说得好。在SemaphoreSlim
上有一些尝试来解决重新进入问题。在过度使用它们之前,应该仔细检查是否需要现有的嵌套锁。尽管如此,我还是强烈推荐这门课。它干净、简单,他首先使用的是框架固有的,并通过异步流传输状态,就像ThreadLocal
对synchronous code.IMO所做的那样。