setters que propiedades para metodos metodo insertar hace getters clases c# async-ctp

que - propiedades c#



¿Cómo llamar a un método asíncrono desde un getter o un setter? (8)

¿Cuál sería la forma más elegante de llamar a un método asíncrono desde un getter o setter en C #?

Aquí hay un pseudo código para ayudarme a explicarme.

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


Como su "propiedad asíncrona" está en un modelo de vista, puede usar AsyncMVVM :

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

Cuidará el contexto de sincronización y la notificación de cambio de propiedad.


Creo que podemos esperar el valor simplemente volviendo primero nulo y luego obtener el valor real, por lo que en el caso de Pure MVVM (proyecto PCL por ejemplo) creo que la siguiente es la solución más 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(); }


No hay ninguna razón técnica para que las propiedades de async no estén permitidas en C #. Fue una decisión de diseño decidida, porque "propiedades asíncronas" es un oxímoron.

Las propiedades deben devolver los valores actuales; no deberían estar iniciando operaciones de fondo.

Generalmente, cuando alguien quiere una "propiedad asincrónica", lo que realmente quiere es uno de estos:

  1. Un método asíncrono que devuelve un valor. En este caso, cambie la propiedad a un método async .
  2. Un valor que puede usarse en el enlace de datos, pero debe calcularse / recuperarse de forma asincrónica. En este caso, utilice un método de fábrica async para el objeto que lo contiene o utilice un async InitAsync() . El valor vinculado a los datos será default(T) hasta que se calcule / recupere el valor.
  3. Un valor que es caro de crear, pero debe almacenarse en caché para uso futuro. En este caso, use AsyncLazy de mi blog o biblioteca AsyncEx . Esto te dará una propiedad que te await .

Actualización: cubro las propiedades asíncronas en una de mis publicaciones recientes de blog "async OOP".


No puede llamarlo de forma asincrónica, ya que no hay soporte de propiedad asíncrono, solo métodos asíncronos. Como tal, hay dos opciones, ambas aprovechando el hecho de que los métodos asíncronos en el CTP son solo un método que devuelve Task<T> o Task :

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

O:

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


Pensé que .GetAwaiter (). GetResult () era exactamente la solución a este problema, ¿no? p.ej:

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


Puede cambiar la libertad a Task<IEnumerable>

y haz algo como:

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

y úsalo como si esperaras MyList;


Realmente necesitaba la llamada para originar desde el método get, debido a mi arquitectura desacoplada. Así que se me ocurrió la siguiente implementación.

Uso: el título está en un modelo de vista o un objeto que puede declarar estáticamente como un recurso de página. Vincúlate y el valor se completará sin bloquear la interfaz de usuario, cuando getTitle () regrese.

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


Una cosa a tener en cuenta: en el caso en que se devuelva un resultado de IEnumerable, el retorno de rendimiento tiene un mejor rendimiento y no requiere la conversión a IEnumerable.

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