C# 异步函数陷入死锁?
目标: 我正在使用redis进行缓存,并尝试获取缓存值(如果不可用),从repo获取并设置缓存值 问题: 客户端js一直在等待,似乎处于某种类型的死锁中 导致问题的代码C# 异步函数陷入死锁?,c#,async-await,func,stackexchange.redis,C#,Async Await,Func,Stackexchange.redis,目标: 我正在使用redis进行缓存,并尝试获取缓存值(如果不可用),从repo获取并设置缓存值 问题: 客户端js一直在等待,似乎处于某种类型的死锁中 导致问题的代码 return await _cacheStore.GetAsync("CacheKey", new TimeSpan(24, 0, 0), async () => await _repo.GetAllAsync()
return await _cacheStore.GetAsync("CacheKey", new TimeSpan(24, 0, 0),
async () =>
await _repo.GetAllAsync()
);
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);
}
代码可以工作,但有点多余,因为我在很多地方一直使用这种模式。
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;
var data=await\u cacheStore.GetAsync(“cacheKey”);
如果(数据==null)
{
数据=等待_repo.GetAllAsync();
_SetAsync(“cacheKey”,数据,新的时间跨度(24,0,0));
}
返回数据;
//下面可能有问题的函数将异步方法传递为Func?????
上述代码调用的函数
return await _cacheStore.GetAsync("CacheKey", new TimeSpan(24, 0, 0),
async () =>
await _repo.GetAllAsync()
);
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);
}
public static async TaskGetAsync(此IRedisCacheStore源代码、字符串键、时间跨度时间、Func>fetch)其中T:class{
if(source.Exists(key)){
返回wait source.GetAsync(键);
}否则{
var result=fetch();
如果(结果!=null){
source.Set(键、结果、时间);
}
返回等待结果;
}
}
公共异步任务>GetAllAsync(){
var result=await_proceducer.ExecuteProcAsync(“存储过程”,null);
返回(结果??新列表()).ToList();
}
公共异步任务>ExecuteProcAsync(字符串存储过程,对象参数){
使用(var conn=\u connection.GetConnection()){
return wait conn.QueryAsync(存储过程,参数,commandType:commandType.storedProcess);
}
这是我的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);
}
公共接口IRedisCacheStore
{
bool存在(字符串键);
T Get(字符串键);
无效集(字符串键、T值、TimeSpan expiredIn);
无效删除(字符串键);
任务存在同步(字符串键);
任务GetAsync(字符串键);
Task SetAsync(字符串键、T值、TimeSpan expiredIn);
任务RemoveAsync(字符串键);
}
问题在于:
var result = fetch();
if (result != null) {
source.Set(key, result, time);
}
fetch()
返回Task
,这就是您试图存储在Redis缓存中的内容,任务(显然)不可序列化。只需使用:
var result = await fetch();
为什么要使用异步委托?为什么不简单地
()=>\u repo.GetAllAsync()
?或者甚至只是\u repo.GetAllAsync
?我也尝试过这种方法,结果也一样,所以我尝试了异步()=>await,它也有相同的结果。客户端js显示挂起,当我调试它时,它只是继续,没有中断,似乎它已经完成了对所有代码请求的处理,除了,如前所述,您根本不需要异步委托,这里也有:var result=fetch();-这应该是var result=await fetch();然后将Task类型的变量存储在redis缓存中(通过Set),谁知道会发生什么呢。async
死锁的最常见原因是,如果您正在同步等待async
代码。您这样做了吗?您可以向代码显示您在此处显示的调用方法吗?理想情况下,提供一个。我应该在var result=fetch()中添加wait;