在c#中从getter或setter调用异步方法的最优雅的方式是什么?

这里有一些伪代码来帮助我解释。

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

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

当前回答

您可以创建事件,并在属性更改时调用事件。 就像这样:

private event EventHandler<string> AddressChanged;
public YourClassConstructor(){
     AddressChanged += GoogleAddressesViewModel_AddressChanged;
}
private async void GoogleAddressesViewModel_AddressChanged(object sender, string e){
      ... make your async call
}
private string _addressToSearch;
public string AddressToSearch
{
    get { return _addressToSearch; }
    set
    {
        _addressToSearch = value;
        AddressChanged.Invoke(this, AddressToSearch);
    }
}

其他回答

您可以将属性更改为Task<IEnumerable>

你可以这样做:

get
{
    Task<IEnumerable>.Run(async()=>{
       return await getMyList();
    });
}

然后像这样使用它 等待MyList;

我认为我们可以等待的值只是返回第一个空,然后得到真实的值,所以在纯MVVM (PCL项目为例)的情况下,我认为下面是最优雅的解决方案:

private IEnumerable myList;
public IEnumerable MyList
{
  get
    { 
      if(myList == null)
         InitializeMyList();
      return myList;
     }
  set
     {
        myList = value;
        NotifyPropertyChanged();
     }
}

private async void InitializeMyList()
{
   MyList = await AzureService.GetMyList();
}

你可以简单地这样做:

public IEnumerable MyList
{
    get
    {
        Task.Run(async () => await MyAsyncMethod);
    }
}

但根据完整的上下文,你可以尝试找到另一种方式来触发你的异步方法,例如:当你调用MyList时,你可以调用第一个MyAsyncMethod..

因为你的“async属性”在一个视图模型中,你可以使用AsyncMVVM:

class MyViewModel : AsyncBindableBase
{
    public string Title
    {
        get
        {
            return Property.Get(GetTitleAsync);
        }
    }

    private async Task<string> GetTitleAsync()
    {
        //...
    }
}

它将负责同步上下文和属性更改通知。

我认为.GetAwaiter().GetResult()正是这个问题的解决方案,不是吗? 例如:

string _Title;
public string Title
{
    get
    {
        if (_Title == null)
        {   
            _Title = getTitle().GetAwaiter().GetResult();
        }
        return _Title;
    }
    set
    {
        if (value != _Title)
        {
            _Title = value;
            RaisePropertyChanged("Title");
        }
    }
}