Como chamar um método asynchronous de um getter ou setter?

Qual seria a maneira mais elegante de chamar um método asynchronous de um getter ou setter em c #?

Aqui está algum pseudo-código para ajudar a me explicar.

async Task MyAsyncMethod() { return await DoSomethingAsync(); } public IEnumerable MyList { get { //call MyAsyncMethod() here } } 

    Não há motivos técnicos para que propriedades async não sejam permitidas em C #. Foi uma decisão de projeto proposital, porque “propriedades assíncronas” é um oxímoro.

    Propriedades devem retornar valores atuais; eles não deveriam estar iniciando operações em segundo plano.

    Normalmente, quando alguém quer uma “propriedade assíncrona”, o que eles realmente querem é um desses:

    1. Um método asynchronous que retorna um valor. Nesse caso, altere a propriedade para um método async .
    2. Um valor que pode ser usado na binding de dados, mas deve ser calculado / recuperado de forma assíncrona. Nesse caso, use um método de fábrica async para o object async InitAsync() ou use um método async InitAsync() . O valor vinculado a dados será default(T) até que o valor seja calculado / recuperado.
    3. Um valor que é caro para criar, mas deve ser armazenado em cache para uso futuro. Nesse caso, use o AsyncLazy do meu blog ou da biblioteca AsyncEx . Isso lhe dará uma propriedade await .

    Update: Eu abordo as propriedades assíncronas em um dos meus posts recentes no blog “async OOP”.

    Você não pode chamá-lo de forma assíncrona, já que não há suporte à propriedade assíncrona, apenas methods asynchronouss. Como tal, existem duas opções, ambas aproveitando o fato de que os methods asynchronouss no CTP são realmente apenas um método que retorna Task ou Task :

     // Make the property return a Task public Task MyList { get { // Just call the method return MyAsyncMethod(); } } 

    Ou:

     // Make the property blocking public IEnumerable MyList { get { // Block via .Result return MyAsyncMethod().Result; } } 

    Eu realmente precisava da chamada para me originar do método get, devido à minha arquitetura desacoplada. Então eu criei a seguinte implementação.

    Uso: O título está em um ViewModel ou em um object que você pode declarar estaticamente como um recurso de página. Ligue-se a ele e o valor será preenchido sem bloquear a interface do usuário, quando getTitle () retornar.

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

    Eu acho que podemos aguardar o valor apenas retornando primeiro nulo e, em seguida, obter o valor real, portanto, no caso do Pure MVVM (projeto PCL, por exemplo), penso que o seguinte é a solução mais elegante:

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

    Eu pensei. GetAwaiter (). GetResult () foi exatamente a solução para este problema, não? por exemplo:

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

    Como sua “propriedade async” está em um viewmodel, você poderia usar o AsyncMVVM :

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

    Ele cuidará do contexto de synchronization e da notificação de alteração de propriedade para você.

    Você pode alterar o proerty para a Task

    e faça algo como:

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

    e usá-lo como esperar MyList;

    Uma coisa a notar: No caso em que um resultado IEnumerable é retornado, o retorno de produção tem melhor desempenho e não requer conversão para IEnumerable.

     public IEnumerable MyList { get { yield return MyAsyncMethod(); } }