2013-01-21 21 views
8

Tôi muốn tải một số dữ liệu trong hàm tạo của một ViewModel nhưng do tính chất không đồng bộ của WinRT, tôi buộc phải sử dụng các phương thức không đồng bộ. Thật không may tôi không thể có một constructor async vì vậy tôi đang cố gắng sử dụng phương pháp không đồng bộ như là một phương pháp đồng bộ. Tôi chắc chắn rằng có một cách tốt hơn để tải dữ liệu (không đồng bộ) vào tải ứng dụng nhưng tâm trí của tôi là vẽ một trống vào lúc này.Tải dữ liệu không đồng bộ của WinRT trong hàm tạo

Tôi đang tìm cách sửa ứng dụng của mình bằng cách sử dụng dòng suy nghĩ tôi đang đi xuống hoặc để khắc phục sự cố này vĩnh viễn bằng phương thức phù hợp hơn.

Mã rất đơn giản (thậm chí thiếu ViewModel) chỉ để minh họa vấn đề tôi đang gặp phải.

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

Trả lời

9

tôi đã viết một bài đăng blog gần đây về async in constructors.

Nói tóm lại, tôi thích một phương pháp async nhà máy:

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

Buộc phương pháp async để chạy đồng bộ thường dẫn đến bế tắc, vì vậy tôi sẽ không khuyên. Điều có mô hình xem là chúng thường hỗ trợ thông báo thay đổi thông qua sự kiện INotifyPropertyChangedPropertyChanged, do đó không cần phải có sẵn tất cả dữ liệu ngay lập tức. Trong thực tế, nếu dữ liệu của bạn không được mã hóa cứng - bạn không nên mong đợi để xem dữ liệu ngay lập tức và bạn rất có thể muốn hiển thị chỉ báo tiến trình trong khi dữ liệu đang tải. Vì vậy ...

Trong hàm khởi tạo của bạn, hãy gọi phương thức khởi tạo không đồng bộ mà không chờ kết quả (vì bạn không thể đợi trong hàm tạo) và trong phương thức khởi tạo khi tất cả dữ liệu có sẵn - gán nó cho thuộc tính/thuộc tính của bạn xem liên kết, nâng cao sự kiện PropertyChanged cho các thuộc tính này và ẩn chỉ báo tiến trình bằng cách thay đổi thuộc tính mô hình khung nhìn kiểm soát khả năng hiển thị của nó.

+2

Lưu ý xử lý lỗi. Nếu 'Task' được trả về bởi phương thức khởi tạo' async' không bao giờ được quan sát, thì bất kỳ ngoại lệ nào cũng sẽ bị âm thầm nuốt chửng. Vì vậy, hãy chắc chắn để có một 'try' /' catch' trong 'InitializeAsync' của bạn hoặc có một phương thức' chờ đợi' kết quả. –

+0

Tất nhiên. Điều này áp dụng cho dù cuộc gọi có trong bộ khởi tạo hay bất kỳ phương thức nào khác có thể dẫn đến trạng thái xấu. –

Các vấn đề liên quan