2013-01-21 59 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

當然。無論調用是在初始化程序還是其他任何可能導致錯誤狀態的方法中,這都適用。 –