2012-07-03 18 views
24

में कभी भी रिटर्न और ऐप लटकता है, मैं एप्लिकेशन लॉन्च पर सेटिंग्स फ़ाइल लोड करने और पढ़ने का प्रयास कर रहा हूं, और लगभग 9 0% समय, await GetFileAsync("filename.xml"); कभी भी वापस नहीं लौटाता है, इस प्रकार, एप्लिकेशन को लटकाता है ।GetFileAsync() का इंतजार करने के लिए कॉल करें WinRT ऐप

समय के बारे में एक चौथाई, यदि मैं कोड के माध्यम से कदम उठाता हूं, तो यह वास्तव में वापस आ जाएगा और फ़ाइल को पढ़ेगा।

App.xaml.cs:

protected override void OnLaunched(LaunchActivatedEventArgs args) 
{ 
    FileLoader.Load().Wait(); 

    // File-load dependent stuff 
} 

FileLoader.cs:

public async static Task Load() 
{ 
    StorageFolder folder = ApplicationData.Current.LocalFolder; 
    StorageFile file; 
    bool fileExists = true; 

    try 
    { 
     // The following line (often) never returns 
     file = await folder.GetFileAsync("filename.xml"); 
    { 
    catch 
    { 
     fileExists = false; 
    } 

    // Do stuff with loaded file 
} 

अगर मैं दृश्य स्टूडियो में आउटपुट विंडो घड़ी

यहाँ कोड का एक बहुत ही सरलीकृत संस्करण है , प्रतीक्षा करने के कुछ समय बाद मुझे "The thread '<No Name>' (0x30c) has exited with code 0 (0x0)."

क्या किसी के पास कोई विचार है यहाँ क्या हो रहा है?

+6

आप यूआई थ्रेड को अवरुद्ध कर रहे हैं जहां तक ​​मैं 'प्रतीक्षा' को कॉल करके देख सकता हूं। यह वास्तव में एक बुरा विचार है। बिल्ली, यह भी हो सकता है कि समस्या का कारण क्या हो रहा है। –

+1

मुझे लगता है कि जॉन बिल्कुल सही है - किसी भी मौके पर आप Async के रूप में ऑनलाइन किया जा सकता है और उसके बाद लोड() कॉल का इंतजार कर सकते हैं? यदि आप नहीं कर सकते हैं, तो दूसरा दृष्टिकोण लोड लोड होने के बाद निष्पादित करने के लिए एक कार्रवाई करने के लिए हो सकता है और फिर अंत में कार्रवाई चलाएं (या, ज़ाहिर है, आप उस कार्य पर जारी रखें जिसका उपयोग लोड() रिटर्न जैसा कि आप async/await से पहले करेंगे :) –

+0

आप दोनों सही थे, जॉन और जेम्स। इनपुट के लिए बहुत बहुत धन्यवाद! मैं मूल रूप से 'प्रतीक्षा' का उपयोग कर रहा था क्योंकि मुझे एहसास नहीं हुआ था कि आप एक ओवरराइड विधि में 'async' जोड़ सकते हैं, और मुझे नहीं पता था कि' ऑनलाउंच 'यूआई थ्रेड पर चल रहा था। 'प्रतीक्षा करें' को हटाकर 'async'' को 'async'' में जोड़कर इसे ठीक किया गया है! काश मैं आपकी टिप्पणी को उत्तर के रूप में चिह्नित कर सकता हूं। – jokeefe

उत्तर

47

डिफ़ॉल्ट रूप से, जब आप awaitTask जो अभी तक पूरा नहीं हुआ है, विधि कैप्चर किए गए संदर्भ (इस मामले में, यूआई संदर्भ) पर फिर से शुरू होती है।

तो, यहाँ क्यों अपने कोड विफल हो रहा है है:

  • OnLaunched कॉल Load (यूआई संदर्भ में)।
  • Load इंतजार कर रहा है। यह अपूर्ण कार्य वापस करने के लिए Load विधि का कारण बनता है और बाद में इसके पूरा होने का शेड्यूल करता है। यह निरंतरता यूआई संदर्भ के लिए निर्धारित है।
  • OnLaunched कार्य पर ब्लॉक Load से लौटा। यह यूआई थ्रेड को अवरुद्ध करता है।
  • GetFileAsync अंत में पूर्ण हो जाता है, और Load के लिए निरंतरता को चलाने का प्रयास करता है।
  • Load के लिए निरंतरता UI थ्रेड उपलब्ध होने की प्रतीक्षा करती है ताकि यह UI संदर्भ में निष्पादित हो सके।
  • इस बिंदु पर, OnLaunchedLoad को पूरा करने के लिए प्रतीक्षा कर रहा है (ऐसा करके यूआई थ्रेड को अवरुद्ध कर रहा है), और Load यूआई थ्रेड को मुक्त होने का इंतजार कर रहा है। गतिरोध।

इन सर्वोत्तम प्रथाओं इस स्थिति से बचने:

  1. अपने "पुस्तकालय" async तरीकों में, ConfigureAwait(false) का उपयोग जब भी संभव हो। आपके मामले में, यह await folder.GetFileAsync("filename.xml"); से await folder.GetFileAsync("filename.xml").ConfigureAwait(false); में बदल जाएगा।
  2. Task एस पर अवरुद्ध न करें; यह async नीचे सभी तरह से है। दूसरे शब्दों में, को await के साथ बदलें।

अधिक जानकारी के लिए:

अद्यतन 2012-07-13: इस जवाब into a blog post शामिल।

+0

उत्कृष्ट जवाब! क्या हो रहा है और संदर्भ लेखों की विस्तृत सूची के बारे में विस्तृत स्पष्टीकरण के लिए बहुत बहुत धन्यवाद। यह सब कुछ स्पष्ट बनाता है। – jokeefe

+0

यह सही था। इसने मुझे इतना दुःख बचाया कि यह अविश्वसनीय था। – ohmusama

+1

मैं चाहता हूं कि एमएस मर जाए। वे निश्चित रूप से ऐसी पागल चीजें प्रदान करने के कारण लोगों की तलाश में हैं। क्यों उन्होंने पुराने पुराने धागे को छोड़ दिया और प्राइमेटिव सिंक नहीं किया ?! बेवकूफों। –

संबंधित मुद्दे