Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinRT async data load in constructor

I want to load some data in the constructor of a ViewModel but due to WinRT's async nature I am forced to use async methods. Unfortunately I cannot have an async constructor so I am trying to use the asynchronous method as a synchronous method. I'm sure there is a much better way of loading data (async) on application load but my mind is drawing a blank at the moment.

I'm either looking for a way to fix my app using the line of thought i'm going down, or to fix this permanently using a more appropriate method.

The code is very simple (even missing the ViewModel) just to demonstrate the issue I'm facing.

public sealed partial class MainPage : Page
{

    public string Data { get; set; }

    public DataService _dataService { get; set; }

    public MainPage()
    {
        this.InitializeComponent();

        _dataService = new DataService();
        var t = _dataService.GetData();

        Data = t.Result;
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }


}

public class DataService
{
    public async Task<string> GetData()
    {
        //Force async
        await Task.Delay(1);

        return "Hello";
    }
}

Kind Regards

like image 949
Peter Avatar asked Jan 21 '13 23:01

Peter


1 Answers

I wrote a recent blog post about async in constructors.

In short, I prefer an async factory method:

public sealed class MyViewModel : INotifyPropertyChanged
{
  private readonly DataService _service;

  private MyViewModel(DataService service)
  {
    _service = service;
  }

  private async Task InitializeAsync()
  {
    var result = await _service.GetData(); // async initialization

    Data = result; // update data-bound properties with the results
  }

  // Data triggers INotifyPropertyChanged on write
  public string Data { get { ... } set { ... } }

  public static async Task<MyViewModel> CreateAsync()
  {
    var ret = new MyViewModel();
    await ret.InitializeAsync();
    return ret;
  }
}
like image 121
Stephen Cleary Avatar answered Oct 06 '22 18:10

Stephen Cleary