使用DI为线程范围缓存昂贵的对象,而不会阻塞(异步)

时间:2018-08-24 10:24:48

标签: c# asynchronous asp.net-core

我想在请求期间缓存一个昂贵的“当前用户”对象。为此,我使用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在我的用户属性中,因为它是一个属性,并且属性不能异步。

所以-如何将这段代码转换为对异步代码有效的代码?

谢谢!

1 个答案:

答案 0 :(得分:0)

将属性转换为可等待的函数

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;
    }    
}