首页 > 解决方案 > 使用 DI 为线程范围缓存昂贵的对象,而不阻塞(异步)

问题描述

我有一个昂贵的“当前用户”对象,我想在请求期间缓存它。为此,我使用 asp.net 核心中的内置 DI,ICurrentUser在请求时创建对象。它看起来像这样:

public class CurrentUserCache : ICurrentUser
{
    public CurrentUserCache(IHttpContextAccessor httpContextAccessor, UserManager userManager)
    {
        var httpContextAccessor1 = httpContextAccessor;
        _user = new Lazy<User>(() => httpContextAccessor1.HttpContext.User != null ? userManager.GetUserAsync(httpContextAccessor1.HttpContext.User).Result : null);
    }

    private Lazy<User> _user;
    public User User {
        get => _user.Value;
        set {}
    }

}

它使用Lazy对象来延迟对象的检索,因为某些控制器操作可能不需要使用它。

我的问题是 - 懒得获取用户的代码里面的代码是阻塞的(.Result)。我不想这样做,因为它非常昂贵。

我不知道如何使这段代码异步。我可以创建一个Lazy<Task<user>>来获取用户,但是我不能await在我的用户属性中这样做,因为它是一个属性并且属性不能是异步的。

那么 - 我怎样才能把这段代码变成适合异步的东西呢?

谢谢!

标签: c#asynchronousasp.net-core

解决方案


将属性变成等待函数

public class CurrentUserCache : ICurrentUser {
    public CurrentUserCache(IHttpContextAccessor httpContextAccessor, UserManager userManager) {
        _user = new Lazy<Task<User>>(() => 
            userManager.GetUserAsync(httpContextAccessor.HttpContext.User)
        );
    }

    private Lazy<Task<User>> _user;

    public Task<User> GetUserAsync() {
        return _user.Value;
    }    
}

推荐阅读