2016-09-11 6 views
2

目的:私はキャッシュにRedisのを使用してレポから取得し、キャッシュ値を設定できない場合は、キャッシュ値を取得しようとしています非同期のFuncはデッドロック状態になりますか?

問題:

クライアント側のjs永遠に待ち続けると動作し、デッドロックのいくつかのタイプ

コード原因問題

return await _cacheStore.GetAsync("CacheKey", new TimeSpan(24, 0, 0), 
       async() => 
        await _repo.GetAllAsync() 
       ); 

コード内にあるように見えますが、ちょっと冗長で、私はこのパターンをたくさん使っています。のFuncとして非同期メソッドを渡す以下

var data = await _cacheStore.GetAsync<List<objectType>>("cacheKey"); 
    if (data == null) 
    { 
     data = await _repo.GetAllAsync(); 
     _cacheStore.SetAsync<List<objectType>>("cacheKey", data, new TimeSpan(24, 0, 0)); 
    } 
    return data; 

//考えられる問題機能?????ここでは、上記のコードで呼ば 機能

public static async Task <T> GetAsync <T> (this IRedisCacheStore source, string key, TimeSpan time, Func < Task <T>> fetch) where T: class { 
if (source.Exists(key)) { 
    return await source.GetAsync <T> (key); 
} else { 
    var result = fetch(); 

    if (result != null) { 
    source.Set(key, result, time); 
    } 

    return await result; 
} 
} 

public async Task < List <ObjectType>> GetAllAsync() { 
var result = await _procExecutor.ExecuteProcAsync <ObjectType> ("Sproc", null); 

return (result ? ? new List <ObjectType>()).ToList(); 
} 

public async Task < IEnumerable <TResult>> ExecuteProcAsync <TResult> (string sproc, object param) { 
    using(var conn = _connection.GetConnection()) { 
    return await conn.QueryAsync <TResult> (sproc, param, commandType: CommandType.StoredProcedure); 
    } 

私のRedisのは、問題がここにある

public interface IRedisCacheStore 
{ 
    bool Exists(string key); 
    T Get<T>(string key); 
    void Set<T>(string key, T value, TimeSpan expiredIn); 
    void Remove(string key); 

    Task<bool> ExistsAsync(string key); 
    Task<T> GetAsync<T>(string key); 
    Task SetAsync<T>(string key, T value, TimeSpan expiredIn); 
    Task RemoveAsync(string key); 
} 
+2

なぜ非同期のデリゲートを使用していますか?単純に '()=> _repo.GetAllAsync()'になるのはなぜですか?あるいは単に '_repo.GetAllAsync'ですか? –

+0

私もそのようにしてみましたが、同じ結果が得られたので、async()=> awaitで試してみましたが、同じ結果が出ました。クライアントjsは保留状態を示していましたが、デバッグを続行するだけでどこでも破られず、すべてのコード要求を処理したことが好きです –

+0

既に述べたように、非同期のデリゲートは必要ありません。var result = fetch( ); - これはvar result = await fetch();でなければなりません。次に、タスクの変数を(Setを介して)redisキャッシュに格納します。これは、その動作を知っています。 – Evk

答えて

3

をキャッシュストアされています

var result = fetch(); 

if (result != null) { 
    source.Set(key, result, time); 
} 

fetch()戻りTask<T>、それはあなたがしようとしているものですRedisキャッシュに格納すると、タスクは(明らかに)直列化できません。ただ使用してください:

var result = await fetch(); 
関連する問題