How to call an async method from a getter or sette

2019-01-02 20:26发布

What'd be the most elegant way to call an async method from a getter or setter in C#?

Here's some pseudo-code to help explain myself.

async Task<IEnumerable> MyAsyncMethod()
{
    return await DoSomethingAsync();
}

public IEnumerable MyList
{
    get
    {
         //call MyAsyncMethod() here
    }
}

标签: c# async-ctp
8条回答
美炸的是我
2楼-- · 2019-01-02 20:50

There is no technical reason that async properties are not allowed in C#. It was a purposeful design decision, because "asynchronous properties" is an oxymoron.

Properties should return current values; they should not be kicking off background operations.

Usually, when someone wants an "asynchronous property", what they really want is one of these:

  1. An asynchronous method that returns a value. In this case, change the property to an async method.
  2. A value that can be used in data-binding but must be calculated/retrieved asynchronously. In this case, either use an async factory method for the containing object or use an async InitAsync() method. The data-bound value will be default(T) until the value is calculated/retrieved.
  3. A value that is expensive to create, but should be cached for future use. In this case, use AsyncLazy from my blog or AsyncEx library. This will give you an awaitable property.

Update: I cover asynchronous properties in one of my recent "async OOP" blog posts.

查看更多
其实,你不懂
3楼-- · 2019-01-02 20:52

I really needed the call to originate from the get method, due to my decoupled architecture. So I came up with the following implementation.

Usage: Title is in a ViewModel or an object you could statically declare as a page resource. Bind to it and the value will get populated without blocking the UI, when getTitle() returns.

string _Title;
public string Title
{
    get
    {
        if (_Title == null)
        {   
            Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
        }
        return _Title;
    }
    set
    {
        if (value != _Title)
        {
            _Title = value;
            RaisePropertyChanged("Title");
        }
    }
}
查看更多
登录 后发表回答