异步延迟加载属性

本文关键字:属性 延迟加载 异步 | 更新日期: 2023-09-27 18:25:37

我已经学会了在存储库中延迟加载属性。现在我想这么做,但我还需要从网页加载一些东西(使用Httpclient),这意味着我的属性将是异步的。

public async Task<List<NewsModel>> News
{
    get
    {
        if (_news == null)
        {
            CacheProvider cache = new CacheProvider();
            object cachedNews = cache.Get("news");
            if (cachedNews == null)
            {
                var client = new HttpClient();
                // await HttpResponse
            }
        }
        return _news;
    }
    set
    {
        _news = value;
    }
}

然而,视觉工作室告诉我

"修饰符async对此项无效"

同时在第一行突出显示单词"新闻"。

有可能做到这一点吗?还是我必须写一个单独的方法?

异步延迟加载属性

不支持异步属性。我在博客上描述了一些变通方法。

在您的情况下,异步延迟初始化听起来是一个很好的解决方案(在我的博客中也有描述)。

首先,具有副作用的属性通常并不那么好。

在这种情况下,简单地读取这个属性就会启动线程、一些网络流量和远程服务器上的一些处理。

这应该是一个方法,而不是属性。

其次,编译器是对的,属性不允许是异步的。现在,您肯定可以写入一个返回异步任务的属性,但不允许使用async关键字。基本上只需从属性声明中去掉async关键字。

但是async在属性上是不合法的,这是另一条线索,表明您应该编写一个方法,而不是属性。

注意在您发布的代码中实际上并不需要async关键字,因为您实际上并没有在其中使用await关键字。因此,您可以简单地完全删除async关键字,因为它不是必需的。事实上,如果您要将其更改为方法,编译器会告诉您这是不必要的,因为您没有使用await(在OP编辑问题后删除。)

您可以使用Lazy属性来返回Task:

class MyClass
{
    readonly Lazy<Task<string>> _text;
    public MyClass()
    {
        _text = new Lazy<Task<string>>(async () =>
        {
            //... await something
            return "Hello!"
        });
    }
    async Task DoSomething()
    {
       var text = await _text.Value;
       //...
    }
}

我认为这个问题是相关的。

简而言之,不支持异步属性。