2013-02-07 11 views
5

मैं वेबफॉर्म में एसिंक का परीक्षण कर रहा हूं और एक बार, मेरा प्रश्न कुछ नहीं करने के बारे में नहीं है, यह इस बारे में है कि पहले से ही कुछ काम करता है, काम करता है। यह मेरा टेस्ट कोड है:वेबफॉर्म में Async/Await - पृष्ठ जीवन चक्र से पहले निरंतरता कैसे चलती है?

protected override void OnPreRender(EventArgs e) 
{ 
    Response.Write("OnPreRender<Br>"); 
} 
protected override void OnPreRenderComplete(EventArgs e) 
{ 
    Response.Write("OnPreRenderComplete<Br>"); 
} 
protected async override void OnLoadComplete(EventArgs e) 
{ 
    Response.Write("OnLoadComplete<br>"); 
    var t1 = Task.Factory.StartNew(() => { 
     System.Threading.Thread.Sleep(2000); 
     return 1; 
    }); 

    //This actually does run: 
    Response.Write((await t1).ToString()); 
} 

तो मेरा कार्य थोड़ी देर के लिए रुकता है और फिर परिणाम लिखता है। मेरा सवाल है - मैं यह काम करने की उम्मीद नहीं करता क्योंकि ऑनलोड लोड विधि से नियंत्रण प्राप्त किया गया है - मैं उम्मीद करता हूं कि पृष्ठ वास्तव में प्रतिपादन समाप्त कर देगा और मेरे कार्य को वापस लौटने से पहले ग्राहक को वापस कर दिया जाएगा।

वास्तविक उत्पादन होता है:

OnLoadComplete 
OnPreRender 
1OnPreRenderComplete 

तो यह स्पष्ट है कि OnLoadComplete विधि नियंत्रण झुकेंगे ताकि OnPreRender चला सकते हैं और उसके बाद OnLoadComplete को लौट नियंत्रित करते हैं। मेरा अनुमानित परिणाम यह था कि "1" कभी प्रिंट नहीं करेगा क्योंकि बाद की घटनाएं आग लग जाएंगी और पृष्ठ का धागा या तो मारा जाएगा या प्रतिक्रिया के बाद पोस्ट-टास्क लेखन होगा। मुझे लगता है, उपर्युक्त दिया गया है, यह आश्चर्य की बात नहीं है कि अगर मैं 10 सेकंड के लिए देरी करता हूं, तो परिणाम बिल्कुल वही है।

मुझे लगता है कि वेबफॉर्म इंजन में कुछ वायरिंग है जो सुनिश्चित करता है कि पेज के जीवन चक्र के अगले चरण से पहले कोई भी प्रतीक्षा पूरी हो जाती है। क्या कोई यह सुनिश्चित करने के लिए जानता है कि यह कैसे होता है? मुझे उन तरीकों में एसिंक/प्रतीक्षा करने का डर है जो डर के लिए अन्य घटनाओं से पहले पूरा करने की आवश्यकता है कि निरंतरता बहुत देर हो जाएगी, लेकिन अगर इसे आंतरिक रूप से संभाला जाता है, तो मैं चिंता नहीं करूंगा।

उत्तर

11

एएसपी.नेट के लिए, आपको केवल .NET 4.5 पर async विधियों का उपयोग करना चाहिए। मैं अंत में क्यों समझाऊंगा।

मेरे पास an article on SynchronizationContext है जो यह एएसपी.NET पर काम करता है इस पर रिक्त स्थान भरने में मदद करता है। सबसे पहले, ध्यान दें कि ASP.NET ने लंबे समय पहले एसिंक्रोनस ऑपरेशंस का समर्थन किया था (.NET 2.0 आईआईआरसी)। आप एसिंक्रोनस ऑपरेशंस को कुछ अलग तरीकों से पंजीकृत कर सकते हैं, लेकिन इस विवरण के लिए हम SynchronizationContext.OperationStarted पर ध्यान केंद्रित करेंगे।

एएसपी.NET प्रत्येक अनुरोध के लिए SynchronizationContext बनाता है, और यह जानता है कि अनुरोध पूरा नहीं हुआ है जब तक कि सभी पंजीकृत संचालन पूरा नहीं हो जाते हैं (SynchronizationContext.OperationCompleted पर कॉल करके)। Event-based asynchronous pattern components (जैसे BackgroundWorker) जब वे प्रारंभ और पूरा करते हैं तो स्वचालित रूप से SynchronizationContext को सूचित करेंगे।

इसी प्रकार, async void विधियां (नया) SynchronizationContext स्वचालित रूप से शुरू होने और पूरा होने पर सूचित करेगा। तो जब आप OnLoadComplete को async void विधि के रूप में ओवरराइड करते हैं, तो संकलक आपके लिए कोड सम्मिलित करता है जो OperationStarted को शुरुआत में और OperationCompleted पर पूरा होने पर कॉल करेगा।

अब तक इतना अच्छा - एएसपी.नेट अब अनुरोध को जीवित रखने के बारे में जानता है जब तक कि उस अनुरोध के लिए सभी असीमित संचालन पूरा नहीं हो जाते। यह सच है भले ही अनुरोध को संसाधित करने वाले कोई धागे न हों।

अब चेतावनी: .NET 4.5 से पहले एएसपी.नेट इसे अनुरोध स्तर पर संभाल लेगा। एएसपी.नेट 4.5 में, लाइफसाइक्ल पाइपलाइन को स्मार्ट बनाया गया था ताकि जब तक एसिंक्रोनस ऑपरेशंस पूरा नहीं हो जाता तब तक यह पृष्ठ जीवन चक्र में देरी करेगा। पुराने एएसपी.नेट के साथ, "प्री" हैंडलर पाइपलाइन में उस बिंदु पर शुरू करेंगे लेकिन बाद में खत्म नहीं हो सकते हैं। नया एएसपी.नेट जीवन के चक्र में आगे बढ़ने से पहले async हैंडलर को पूरा करने के लिए शेष पृष्ठ निष्पादन में देरी करेगा।

इसके अलावा, एएसपी.NET 4.5 पता लगाएगा कि आपने async हैंडलर का उपयोग किया है, जहां कोई नहीं होना चाहिए, और आपको त्रुटि के बारे में सूचित करेगा।

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