2013-01-21 18 views
8

我想在ViewModel的构造函数中加载一些数据,但由于WinRT的异步性质,我不得不使用异步方法。不幸的是,我不能有一个异步构造函数,所以我尝试使用异步方法作为同步方法。我确信在加载应用程序时有更好的方法来加载数据(异步),但我现在的想法是空白。构造函数WinRT异步数据加载

我正在寻找一种方法来修复我的应用程序,使用我要下去的思路,或者使用更合适的方法来解决这个问题。

该代码非常简单(甚至缺少ViewModel)只是为了演示我面临的问题。

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

亲切的问候

回答

9

我写了一个最近的博客帖子大约async in constructors

总之,我更喜欢一个async工厂方法:

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; 
    } 
} 
2

强制异步方法同步运行,通常会导致死锁,所以我不会建议。查看模型的事情是,他们通常通过事件支持更改通知,因此不需要立即获得所有数据。事实上,如果您的数据不是硬编码的 - 您不应该期望立即看到数据,并且您可能希望在数据加载时显示进度指示器。因此...

在您的构造函数中调用异步初始化方法而无需等待结果(因为您无法在构造函数中等待)以及初始化方法中的所有数据都可用时 - 将其分配给您的属性/属性视图绑定到,为这些属性引发PropertyChanged事件,并通过更改控制其可见性的视图模型属性来隐藏进度指示器。

+2

记住错误处理。如果''async'初始化方法返回的'Task'永远不会被观察到,任何异常都会被悄悄吞下。所以一定要在'InitializeAsync'中有一个'try' /'catch'或者另一个方法'await'结果。 –

+0

当然。无论调用是在初始化程序还是其他任何可能导致错误状态的方法中,这都适用。 –