C# 从Redis检索多把钥匙时死锁

C# 从Redis检索多把钥匙时死锁,c#,async-await,task-parallel-library,stackexchange.redis,C#,Async Await,Task Parallel Library,Stackexchange.redis,我试图使用StackExchangeClient并行地向redis获取此查询的结果,但不知何故,我在死锁中运行,不确定在哪里 检索数据的方法: public LiveData Get(string sessionId) { return GetAsync(sessionId).Result; } private async Task<LiveData> GetAsync(string sessionId) { var basketTask = GetBasketAs

我试图使用StackExchangeClient并行地向redis获取此查询的结果,但不知何故,我在死锁中运行,不确定在哪里

检索数据的方法:

public LiveData Get(string sessionId)
{
    return GetAsync(sessionId).Result;
}

private async Task<LiveData> GetAsync(string sessionId)
{
    var basketTask = GetBasketAsync(sessionId);
    var historyTask = GetHistoryAsync(sessionId);
    var capturedDataTask = GetCapturedDataAsync(sessionId);

    var basket = await basketTask;
    var history = await historyTask;
    var capturedData = await capturedDataTask;

    return new LiveData
    {
        Basket = basket.IsNullOrEmpty
            ? new List<Product>()
            : JsonConvert.DeserializeObject<List<Product>>(basket),
        History = history.Select(cachedProduct
            => JsonConvert.DeserializeObject<Product>(cachedProduct.Value.ToString())).ToList(),
        CapturedData = capturedData.ToDictionary<HashEntry, string, object>(
            hash => hash.Name, hash => JsonConvert.DeserializeObject(hash.Value))
    };
}
从redis获取缓存数据的方法有:

private async Task<RedisValue> GetBasketAsync(string key)
{
    key = $"{key}{BasketSuffix}";
    var redisDb = RedisConnection.Connection.GetDatabase();
    redisDb.KeyExpireAsync(key, _expire);

    return await redisDb.StringGetAsync(key);
}

private async Task<HashEntry[]> GetHistoryAsync(string key)
{
    key = $"{key}{HistorySuffix}";
    var redisDb = RedisConnection.Connection.GetDatabase();
    redisDb.KeyExpireAsync(key, _expire);

    return await redisDb.HashGetAllAsync(key);
}

private async Task<HashEntry[]> GetCapturedDataAsync(string key)
{
    key = $"{key}{CapturedDataSuffix}";
    var redisDb = RedisConnection.Connection.GetDatabase();
    redisDb.KeyExpireAsync(key, _expire);

    return await redisDb.HashGetAllAsync(key);
}

我认为这样调用KeyExpireAsync很好,只是因为可以触发并忘记,但不确定这是否相关,我甚至尝试过删除它,但它仍然被阻止

死锁的来源是以下代码片段:

public LiveData Get(string sessionId)
{
    return GetAsync(sessionId).Result;
}
相反,请始终以正确的方式异步调用它:

public async Task<LiveData> Get(string sessionId)
{
    return await GetAsync(sessionId);
}
我理解您在.KeyExpireAsync调用中不使用wait关键字的想法,但如果我正在编写此代码,我肯定会像我演示的那样等待它。这是一个代码的气味有火灾和忘记,可以很容易地避免

async Task<RedisValue> GetBasketAsync(string key)
{
    key = $"{key}{BasketSuffix}";
    var redisDb = RedisConnection.Connection.GetDatabase();
    await redisDb.KeyExpireAsync(key, _expire);

    return await redisDb.StringGetAsync(key);
}