Lazy load properties with Async

2019-04-09 14:25发布

I've learned to lazy load properties in my repository. Now I'd like to do that, but I also need to load something from a web page (using Httpclient) which means my property will be async.

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

However, visual studio is telling me that

"The modifier async is not valid for this item"

while highlighting the word "News" in the first line.

Is it possible to do this? Or do I have to write a separate method?

4条回答
萌系小妹纸
2楼-- · 2019-04-09 14:30

Asynchronous properties are not supported. I describe a number of workarounds on my blog.

In your case, it sounds like asynchronous lazy initialization would be a good solution (also described on my blog).

查看更多
Luminary・发光体
3楼-- · 2019-04-09 14:42

First of all, properties with side-effects are usually not all that good.

In this case, simply reading this property would kick off a thread, some network traffic, and some processing on a remote server.

This should be a method, not a property.

Secondly, the compiler is right, properties are not allowed to be asynchronous. Now, you can definitely write a property that returns an asynchronous task, but you're not allowed to use the async keyword. Basically just take away the async keyword from the property declaration.

But the fact that async is not legal on properties is another clue that you should write a method, not a property.

Note The async keyword is not actually required in the code you've posted, since you're not actually using the await keyword in there. As such, you can simply remove the async keyword altogether, since it is not required. In fact, if you were to change this over to a method, the compiler will tell you that it is unnecessary since you're not using await. (Removed after OP edited the question.)

查看更多
手持菜刀,她持情操
4楼-- · 2019-04-09 14:48

I think this question is related.

In short - async properties are not supported.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-04-09 14:51

You can use a Lazy property that returns a 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;
       //...
    }
}
查看更多
登录 后发表回答