2013-01-21 22 views
8

मैं व्यूमोडेल के निर्माता में कुछ डेटा लोड करना चाहता हूं लेकिन WinRT की एसिंक प्रकृति के कारण मुझे एसिंक विधियों का उपयोग करने के लिए मजबूर होना पड़ता है। दुर्भाग्यवश मेरे पास एसिंक कन्स्ट्रक्टर नहीं हो सकता है इसलिए मैं एसिंक्रोनस विधि को सिंक्रोनस विधि के रूप में उपयोग करने का प्रयास कर रहा हूं। मुझे यकीन है कि एप्लिकेशन लोड पर डेटा (async) लोड करने का एक बेहतर तरीका है लेकिन मेरा दिमाग इस समय एक खाली चित्र खींच रहा है।कन्स्ट्रक्टर में WinRT async डेटा लोड

मैं या तो विचार कर रहा हूं कि मैं नीचे जा रहा विचार की रेखा का उपयोग करके अपने ऐप को ठीक करने का तरीका ढूंढ रहा हूं, या इसे एक और उचित विधि का उपयोग करके स्थायी रूप से ठीक करने के लिए एक तरीका ढूंढ रहा हूं।

कोड जिस समस्या का सामना कर रहा है उसका प्रदर्शन करने के लिए कोड बहुत सरल है (यहां तक ​​कि व्यूमोडेल भी गायब है)।

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

async तरीकों जबरदस्ती तुल्यकालिक आमतौर पर चलाने के लिए गतिरोध की ओर जाता है, इसलिए मुझे लगता है कि सिफारिश नहीं होगा। दृश्य मॉडल के साथ बात यह है कि वे आम तौर पर INotifyPropertyChangedPropertyChanged ईवेंट के माध्यम से परिवर्तन अधिसूचनाओं का समर्थन करते हैं, इसलिए सभी डेटा तुरंत उपलब्ध होने की आवश्यकता नहीं है। असल में यदि आपका डेटा हार्ड-कोड नहीं है - तो आपको तुरंत डेटा देखने की उम्मीद नहीं करनी चाहिए और डेटा लोड होने के दौरान आप एक प्रगति सूचक दिखाना चाहते हैं। इस प्रकार ...

अपने कन्स्ट्रक्टर में परिणाम की प्रतीक्षा किए बिना एक एसिंक प्रारंभिक विधि को कॉल करें (क्योंकि आप किसी कन्स्ट्रक्टर में प्रतीक्षा नहीं कर सकते हैं) और प्रारंभिक विधि में जब सभी डेटा उपलब्ध होता है - इसे अपनी संपत्ति/गुणों को असाइन करें इन गुणों के लिए PropertyChanged ईवेंट को बढ़ाने के लिए बाध्य देखें और दृश्य दृश्य संपत्ति को बदलकर प्रगति संकेतक को छुपाएं जो इसकी दृश्यता को नियंत्रित करता है।

+2

दिमाग में त्रुटि रखने में त्रुटि रखें। यदि 'async' प्रारंभिक विधि द्वारा लौटाया गया 'कार्य' कभी नहीं देखा जाता है, तो कोई भी अपवाद चुपचाप निगल जाएगा। तो सुनिश्चित करें कि आपके 'InitializeAsync' में' try'/'catch' होना चाहिए या परिणाम का एक और तरीका 'प्रतीक्षा करें' है। –

+0

बेशक। यह इस बात पर ध्यान दिए बिना कि कॉल प्रारंभकर्ता या किसी अन्य विधि में है जो खराब स्थिति का कारण बन सकता है। –