2011-06-22 15 views
5

मैं async CTP के साथ अपने पहले खेल में लगभग 15 मिनट ... (अच्छा) हूं।async ctp रिकर्सन

यहाँ एक बहुत आसान सर्वर मैं एक साथ दस्तक दी है या नहीं:

internal class Server 
{ 
    private HttpListener listener; 
    public Server() 
    { 
     listener = new HttpListener(); 
     listener.Prefixes.Add("http://*:80/asynctest/"); 
     listener.Start(); 
     Go(); 
    } 

    async void Go() 
    { 
     HttpListenerContext context = await listener.GetContextAsync(); 
     Go(); 
     using (var httpListenerResponse = context.Response) 
     using (var outputStream = httpListenerResponse.OutputStream) 
     using (var sw = new StreamWriter(outputStream)) 
     { 
      await sw.WriteAsync("hello world"); 
     } 
    } 
} 

के रूप में देखा जा सकता है, async विधि Go ही कहता है। क्लासिक गैर-एसिंक दुनिया में, यह एक ढेर ओवरफ्लो का कारण बनता है। मुझे लगता है कि यह एसिंक विधि के साथ मामला नहीं है, लेकिन मैं निश्चित रूप से, एक तरफ या दूसरे को सुनिश्चित करना चाहता हूं। किसी को?

उत्तर

13

के सरल कुछ में यह टूट करते हैं:

async static void Go() 
{ 
    await Something(); 
    Go(); 
    await SomethingElse(); 
} 

कैसे इस के साथ संकलक सौदा?

मूल रूप से इस इस स्केच की तरह कुछ हो जाता है:

class HelperClass 
{ 
    private State state = STARTSTATE; 
    public void DoIt() 
    { 

     if (state == STARTSTATE) goto START; 
     if (state == AFTERSOMETHINGSTATE) goto AFTERSOMETHING; 
     if (state == AFTERSOMETHINGELSESTATE) goto AFTERSOMETHINGELSE; 

     START: 
     { 
      state = AFTERSOMETHINGSTATE; 
      var awaiter = Something().MakeAnAwaiter(); 
      awaiter.WhenDoneDo(DoIt); 
      return; 
     } 

     AFTERSOMETHING: 
     { 
      Go(); 
      state = AFTERSOMETHINGELSESTATE; 
      var awaiter = SomethingElse().MakeAnAwaiter(); 
      awaiter.WhenDoneDo(DoIt); 
      return; 
     } 

     AFTERSOMETHINGELSE: 

     return; 
    } 

    static void Go() 
    { 
     var helper = new HelperClass(); 
     helper.DoIt(); 
    } 

अब बस आपको याद है कि जब प्रत्येक अतुल्यकालिक आपरेशन पूरा करता है, "छदाम" (उचित पर संदेश पाश से फिर से कहा जाता है किया जाना निर्धारित है पाठ्यक्रम के सहायक का उदाहरण)।

तो क्या होता है? इसका हल करना। आप पहली बार जाओ कॉल करते हैं। यह सहायक नंबर एक बनाता है और DoIt को कॉल करता है। वह कुछ कहता है(), एक कार्य वापस ले जाता है, उस कार्य के लिए एक प्रतीक्षाकर्ता बनाता है, "जब आप पूरा कर लें, तो सहायक 1 कॉल करें।" यह लौटता है और लौटाता है।

कार्य के बाद एक सेकंड का दसवां कार्य पूरा हो जाता है और संदेश लूप सहायक 1 के DoIt को कॉल करता है। हेल्पर 1 का राज्य AFTERSOMETHINGSTATE है, इसलिए हम गेटो लेते हैं और गो कॉल करते हैं। यह सहायक 2 बनाता है और उस पर DoIt कहते हैं। वह कुछ() को कॉल करता है, एक कार्य वापस लेता है, उस कार्य के लिए एक प्रतीक्षाकर्ता बनाता है, "जब आप पूरा कर लेंगे, हेल्पर 2 पर DoIt को कॉल करें" और हेल्पर 1 के DoIt पर नियंत्रण वापस लौटाता है। वह SomethingElse को कॉल करता है, उस कार्य के लिए एक प्रतीक्षाकर्ता बनाता है, और यह कहता है "जब आप कुछ और कर रहे हैं, तो हेल्पर 1 की DoIt पर कॉल करें"। फिर यह लौटता है।

अब हमारे पास दो कार्य उत्कृष्ट हैं और ढेर पर कोई कोड नहीं है। कार्यों में से एक पहले पूरा हो जाएगा। मान लीजिए SomethingElse कार्य पहले पूरा करता है। संदेश लूप helper1.DoIt() कहते हैं, जो तुरंत लौटता है। हेल्पर 1 अब कचरा है।

बाद में संदेश लूप सहायक 2.DoIt(), और शाखाओं को AFTERSOMETHING पर कॉल करता है। अब जाओ() कहा जाता है, जो हेल्पर 3 बनाता है ...

तो नहीं, यहां कोई असहनीय रिकर्सन नहीं है। जब भी एसिंक्रोनस से कुछ() शुरू होता है तब तक इसे निष्पादित करता है और फिर यह अपने कॉलर पर वापस आता है। "कुछ" के बाद सामान को कॉल बाद में होता है। एक बार में "जाओ" केवल स्टैक पर ही होता है।

+0

अच्छा। मुझे बहुत संदेह था, लेकिन निर्माण के यांत्रिकी को विस्तार से देखना अच्छा था। इस तरह के एक व्यापक उत्तर के लिए धन्यवाद (हमेशा के रूप में!)। – spender

+0

@ स्पेंडर: आपका स्वागत है! सीटीपी का आनंद लें, और अगर आपके पास प्रश्न, टिप्पणियां, चिंताओं, प्रशंसा, रचनात्मक आलोचनाएं आदि हैं, तो उन्हें असिन सीटीपी फोरम में पोस्ट करें। हमारे पास प्रोग्राम मैनेजर हैं जो हर दिन पढ़ते हैं और उस सुविधा पर उपयोगकर्ता प्रतिक्रिया इकट्ठा करते हैं जो हमारे लिए बहुत उपयोगी है। –

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