基于异步生成器创建内存缓存的方法及CS0149错误解决
错误修复方案
错误原因
CS0149报错的核心是GetAsync方法的第二个参数类型定义错误:
你当前使用的Task<Func<T>>代表「一个已启动的Task实例,其返回值为同步委托Func<T>」,直接执行generatorasync()相当于把Task对象当作方法调用,不符合C#语法规范。
修正方法
将参数类型改为Func<Task<T>>,代表「一个返回异步任务的委托,调用后会执行你定义的EF Core查询等异步逻辑」。
修正后的完整代码如下:
using Microsoft.Extensions.Caching.Memory; using System; using System.Threading.Tasks; public sealed class CacheManager { readonly IMemoryCache memoryCache; public CacheManager(IMemoryCache memoryCache) { this.memoryCache = memoryCache; } public async Task<T> GetAsync<T>(string key, Func<Task<T>> generatorAsync) { var cacheEntry = await memoryCache.GetOrCreateAsync<T>(key, async entry => { entry.SlidingExpiration = TimeSpan.FromMinutes(15); // 可选:增加绝对过期时间,避免高频访问导致缓存永久不更新 entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2); return await generatorAsync(); }); return cacheEntry; } }
调用示例(结合EF Core查询):
// 服务中注入CacheManager和你的DbContext后调用 var products = await _cacheManager.GetAsync("product_all", async () => { return await _context.Products.AsNoTracking().ToListAsync(); });
异步内存缓存实现最佳实践
- 双过期策略配置:滑动过期基础上新增绝对过期,避免热点数据因持续访问长期不更新,导致数据不一致
- 空值缓存处理:如果数据源返回空结果,可设置较短的过期时间缓存空值,避免缓存穿透,大量无效请求直接访问数据库
- 缓存键规范管理:不同业务场景的缓存键增加统一前缀,比如用户相关缓存加
user_前缀,商品相关加product_前缀,避免键冲突,也方便后续批量清理同类型缓存 - 异常捕获:在异步生成委托中增加异常处理逻辑,避免数据源查询失败时导致整个缓存获取流程崩溃,同时不要缓存异常结果
- 热点key防击穿:对于访问量极高的缓存key,可增加本地锁逻辑,避免缓存失效瞬间大量请求同时查询数据库,造成数据库压力陡增
内容的提问来源于stack exchange,提问作者Andrus
相关产品推荐
相关产品推荐

