2012-06-14 8 views
11

आंतरिक हैंडलर के SendAsync() को कॉल करने से पहले, और आंतरिक हैंडलर पूरा होने के बाद सिंक्रोनस काम निष्पादित करने से पहले मैं समकालिक काम निष्पादित करने में सहज हूं। उदाहरण:एक प्रतिनिधिमंडल को एसिंक कॉल (एएसपी.नेट एमवीसी वेब एपीआई) कैसे बनाना चाहिए?

protected override Task<HttpResponseMessage> SendAsync( 
    HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    // do some sync work before inner handler here 

    var sendTask = base.SendAsync(request, cancellationToken); 
    return sendTask.ContinueWith( 
     task => { // do some sync work afterwards here }); 
} 

हालांकि, अब मुझे एक प्रतिनिधि हैंडलर के भीतर से आईओ बाध्य संचालन को कॉल करने की आवश्यकता है। आईओ बाध्य ऑपरेशन पहले से ही Task<bool> के रूप में लपेटा गया है। मुझे यह निर्धारित करने के लिए परिणाम का उपयोग करने की आवश्यकता है कि आंतरिक हैंडलर पर जारी रहना है या नहीं।

एक उदाहरण अनुरोध को अधिकृत करने के लिए नेटवर्क कॉल करेगा। मुझे मौजूदा सिस्टम के साथ एकीकृत करने के लिए ऐसा करना है। आम तौर पर, मुझे लगता है कि इस समस्या के लिए वैध परिदृश्य हैं, और इसमें एक व्यावहारिक समाधान होना चाहिए।

इस मामले में SendAsync को कार्यान्वित करने का सही तरीका क्या है, ताकि मैं आईओ बाध्य कार्य को असीमित रूप से निष्पादित कर सकूं और फिर असीमित रूप से आंतरिक हैंडलर निष्पादित करना जारी रखूं?

मुख्य बिंदु यह है कि मैं निश्चित होना चाहता हूं कि अनुरोध थ्रेड किसी भी बिंदु पर अवरुद्ध नहीं छोड़ा गया है।

उत्तर

15

ठीक है, मुझे लगता है कि मैंने यह क्रैक किया है। मैं इसे एक प्रमाणीकरण परिदृश्य के साथ चित्रित कर रहा हूं: मैं उपयोगकर्ता को असीमित रूप से प्रमाणित करना चाहता हूं और परिणाम का उपयोग यह तय करने के लिए करता हूं कि 401 को वापस करना है या संदेश हैंडलर श्रृंखला के साथ जारी रखना है या नहीं।

केंद्रीय समस्या यह है कि आप आंतरिक हैंडलर SendAsync() को कॉल नहीं कर सकते हैं जब तक कि आपके पास एसिंक्रोनस प्रमाणीकरण से नतीजा न हो।

मेरे लिए मुख्य अंतर्दृष्टि निष्पादन के प्रवाह को नियंत्रित करने के लिए कार्य नियंत्रक स्रोत (टीसीएस) का उपयोग करना था। इससे मुझे टीसीएस से कार्य वापस करने में मदद मिली और जब भी मुझे पसंद आया तो इसका परिणाम सेट करें - और सबसे महत्वपूर्ण बात यह है कि SendAsync() को कॉल करने में देरी करने तक मुझे पता है कि मुझे इसकी आवश्यकता है।

तो, मैंने टीसीएस स्थापित किया और फिर प्राधिकरण को करने का कार्य शुरू किया। इस पर निरंतरता में, मैं परिणाम देखता हूं। यदि अधिकृत है, तो मैं आंतरिक हैंडलर चेन का आह्वान करता हूं और इस (किसी थ्रेड अवरोध से परहेज) को टीसीएस पूरा करता है। अगर प्रमाणीकरण विफल रहता है तो मैं वहां टीसीएस को पूरा करता हूं और फिर 401 के साथ।

इसका नतीजा यह है कि बिना किसी थ्रेड अवरोध के बदले में असीमित कार्यों को निष्पादित किया जाता है। मैंने इसका परीक्षण किया है और ऐसा लगता है कि यह ठीक काम करता है।

यह .NET 4.5 में एसिंक/प्रतीक्षा वाक्यविन्यास के साथ बहुत अच्छा है हालांकि ... हालांकि टीसीएस के साथ दृष्टिकोण मूल रूप से कवर के तहत हो रहा है, कोड बहुत आसान है।

आनंद लें!

पहला स्निपेट वेब एपीआई बीटा के साथ .NET 4.0 पर बनाया गया था - दूसरा .NET 4.5/वेब एपीआई आरसी पर।

protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>(); 

    // Authorize() returns a started 
    // task that authenticates the user 
    // if the result is false we should 
    // return a 401 immediately 
    // otherwise we can invoke the inner handler 
    Task<bool> authenticationTask = Authorize(request); 

    // attach a continuation... 
    authenticationTask.ContinueWith(_ => 
    { 
     if (authenticationTask.Result) 
     { 
      // authentication succeeded 
      // so start the inner handler chain 
      // and write the result to the 
      // task completion source when done 
      base.SendAsync(request, cancellationToken) 
       .ContinueWith(t => taskCompletionSource.SetResult(t.Result)); 
     } 
     else 
     { 
      // authentication failed 
      // so complete the TCS immediately 
      taskCompletionSource.SetResult(
       new HttpResponseMessage(HttpStatusCode.Unauthorized)); 
     } 
    }); 

    return taskCompletionSource.Task; 
} 

यहाँ है एक .NET 4.5/वेब API रिलीज़ उम्मीदवार संस्करण है जो नए के साथ एक बहुत sexier है async/इंतजार वाक्य रचना:

protected override async Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    // Authorize still has a Task<bool> return type 
    // but await allows this nicer inline syntax 
    var authorized = await Authorize(request); 

    if (!authorized) 
    { 
     return new HttpResponseMessage(HttpStatusCode.Unauthorized) 
     { 
      Content = new StringContent("Unauthorized.") 
     }; 
    } 

    return await base.SendAsync(request, cancellationToken); 
} 
+0

आप 'Authorize' कैसे लागू किया था? क्या आपने एक नया 'HttpClient' instanciated किया था? – JobaDiniz

+0

प्राधिकरण का कार्यान्वयन यहां प्रासंगिक नहीं है - यह केवल एक असीमित कार्य है जो यह निर्धारित करता है कि अनुरोध की अनुमति है या नहीं - आप इसे कैसे लागू करते हैं, यह आपके ऊपर है।उदाहरण के लिए, एक डेटाबेस जांच कर सकता है यह देखने के लिए कि वर्तमान उपयोगकर्ता के पास कुछ bespoke व्यवसाय नियमों के आधार पर वर्तमान अनुरोध करने के लिए उपयोग है या नहीं। –

+0

मैं बस सोच रहा था कि क्या आप एक और http अनुरोध करते हैं, यह सब कुछ है ... मेरे परिदृश्य में मुझे वर्तमान में एक और http कॉल करने की आवश्यकता है, और मुझे एक और 'HttpClient' instanciated है। मैं सोच रहा था कि क्या मैं हैंडलर के अंदर मौजूदा एक का पुन: उपयोग कर सकता हूं, लेकिन ऐसा लगता है कि मैं – JobaDiniz

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

  • कोई संबंधित समस्या नहीं^_^