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所做的那样。