使用Async的延迟加载属性

时间:2013-07-31 16:15:09

标签: c# asynchronous

我已经在我的存储库中学习了延迟加载属性。现在我想这样做,但我还需要从网页加载一些东西(使用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;
    }
}

然而,visual studio告诉我

  

“修饰符异步对此项目无效”

同时在第一行突出显示“新闻”一词。

有可能这样做吗?或者我是否必须编写单独的方法?

4 个答案:

答案 0 :(得分:10)

不支持异步属性。我在博客上描述了number of workarounds

在您的情况下,听起来asynchronous lazy initialization会是一个很好的解决方案(我的博客上也有描述)。

答案 1 :(得分:5)

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

在这种情况下,只需读取这个属性就会启动一个线程,一些网络流量,以及远程服务器上的一些处理。

这应该是一种方法,而不是财产。

其次,编译器是正确的,不允许属性是异步的。现在,您绝对可以编写返回异步任务的属性,但不允许您使用async关键字。基本上只是从属性声明中删除async关键字。

async在属性上不合法的事实是另一个线索,你应该写一个方法,而不是一个属性。

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

答案 2 :(得分:3)

您可以使用返回任务的Lazy属性:

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

答案 3 :(得分:1)

我认为this question是相关的。

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