2017-02-16 10 views
8

में async प्रतीक्षा का उपयोग करने के लिए सर्वोत्तम अभ्यास मेरे पास .NET कोर वेब एपीआई है जो सेवा परत के रूप में है। सेवा परत में सभी ईएफ कोड हैं।वेबपी

यदि यह कोड

protected Task<IActionResult> NewTask(Func<IActionResult> callback) 
{ 
    return Task.Factory.StartNew(() => 
    { 
     try 
     { 
      return callback(); 
     } 
     catch (Exception ex) 
     { 
      Logger.LogError(ex.ToString()); 
      throw; 
     } 
    }); 
} 

नियंत्रक कार्रवाई में साथ basecontroller है मैं उपरोक्त विधि में सेवा के लिए उदाहरण के लिए सभी कॉल्स लपेट :

[HttpGet("something")] 
public async Task<IActionResult> GetSomething(int somethingId) 
{ 
    return await NewTask(() => 
    { 
     var result = _somethingService.GetSomething(somethingId); 

     if (result != null) 
      return Ok(result); 
     else 
      return NotFound("Role not found"); 
    }); 
} 

क्या यह सही पैटर्न कल पर विचार कर रहा है मेरे पास कार्रवाई में एक से अधिक सेवा कॉल हो सकती हैं या अन्य webservice पर कॉल कर सकती हैं। कृपया सलाह दें।

+4

आप क्या यहाँ पूरा करने के लिए कोशिश कर रहे हैं के बारे में अधिक जानकारी दे कृपया कर सकते हैं:

आपका कार्यों कुछ इस तरह देखना चाहिए? आपका कोड मूल रूप से पृष्ठभूमि थ्रेड पर सिंक्रोनस काम करके असीमित काम करता है। Task.Factory.StartNew का उपयोग करके उल्लेख नहीं करना बहुत खतरनाक है और आपको इसके बजाय कार्य का उपयोग करना चाहिए। लेकिन आपको कार्य की आवश्यकता भी नहीं है। यहां रुन। –

+0

कुछ सेवा में कुछ क्रूड ऑपरेशंस हैं जो इकाई फ्रेमवर्क कोर का उपयोग करते हैं। आज भी मेरे पास फीड सेवा जैसी एक सेवा हो सकती है जिसमें httpclient का उपयोग करके बाहरी वेब से फ़ीड प्राप्त करने के लिए कॉल किया जाएगा। मैं चाहता हूं कि मेरी एपीआई एसिंक से प्रतीक्षा करें। चीज़ के ऊपर चीज़ों से ऊपर की जरूरत है। इन जरूरतों को पूरा करेगा + कोई चिंता या सुधार। – krishna

उत्तर

17

मैं async से लाभ के लिए अपने एपीआई का इंतजार पैटर्न ऊपर thing.does इन जरूरतों

नहीं है, यदि ऐसा नहीं होता सेवा करेंगे चाहते हैं। थ्रेड पूल पर सिंक्रोनस काम चलाना आपको न तो लाभ के साथ सिंक्रोनस और असीमित कोड की कमी देता है।

कुछ सेवा है जो

वर्तमान में entityframework कोर का प्रयोग कुछ crud कार्य किया है, अपनी कार्रवाई विधि मैं क्या "नकली अतुल्यकालिक" कहते है - यह अतुल्यकालिक लग रहा है (जैसे, await का प्रयोग करके) वास्तव में, लेकिन है बस पृष्ठभूमि धागे पर ब्लॉकिंग कोड चल रहा है। एएसपी.नेट पर, आप सच एसिंक्रोनिमी चाहते हैं, जिसका अर्थ है कि आपको सभी तरह से एसिंक होना चाहिए। एएसपी.नेट पर यह बुरा क्यों है, इसके बारे में अधिक जानने के लिए, मेरे intro to async on ASP.NET article का पहला भाग देखें (यह ज्यादातर एएसपी.नेट गैर-कोर से संबंधित है, लेकिन सिंक्रोनस बनाम एसिंक्रोनस अनुरोधों के बारे में बात करने वाला पहला भाग किसी भी प्रकार के सर्वर के लिए मान्य है)।

यह वास्तव में असीमित बनाने के लिए, आपको निम्नतम स्तर पर शुरू करना चाहिए - इस मामले में, आपके ईएफसीओआर कॉल। वे सभी एसिंक्रोनि का समर्थन करते हैं। तो, x.FirstOrDefault() जैसे await x.FirstOrDefaultAsync() (और आपके सभी क्रिएटिव/अपडेट/डिलीट आदि के लिए) जैसी एपीआई कॉल को प्रतिस्थापित करें।

फिर async/await को स्वाभाविक रूप से वहां से बढ़ने की अनुमति दें; संकलक आपको मार्गदर्शन करेगा। आप अपने somethingService पर अतुल्यकालिक तरीकों जो इस तरह के रूप में सेवन किया जा सकता के साथ खत्म हो जाएगा:

[HttpGet("something")] 
public async Task<IActionResult> GetSomething(int somethingId) 
{ 
    var result = await _somethingService.GetSomethingAsync(somethingId); 
    if (result != null) 
    return Ok(result); 
    else 
    return NotFound("Role not found"); 
} 
+0

ef core async कॉल सिंक कॉल की तुलना में धीमी हैं कृपया सलाह दें। – krishna

+0

@ उपयोगकर्ता 1603828: अंतर नगण्य होना चाहिए। यदि आप जो नहीं देख रहे हैं, तो मैं इसके बारे में ईएफ टीम से संपर्क करने की सलाह देता हूं। –

+0

आपके ब्लॉग के माध्यम से जा रहा है बहुत सारी रोचक जानकारी है। – krishna

6

ठीक है, सब से पहले, आप Task.Factory.StartNew का उपयोग कर बंद करो और Task.Run का उपयोग केवल जब तुम भारी सीपीयू बाध्य काम होना चाहिए कि आप थ्रेड पूल थ्रेड पर चलना चाहते हैं। आपके मामले में आपको वास्तव में इसकी आवश्यकता नहीं है। आपको यह भी याद रखना चाहिए कि विधि को कार्यान्वित करते समय आपको केवल Task.Run का उपयोग करना चाहिए और विधि के कार्यान्वयन में नहीं। आप here के बारे में अधिक पढ़ सकते हैं।

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

मूल रूप से आपकी सेवा कुछ इस तरह दिखना चाहिए (यदि आप सुनिश्चित करें कि आप एक सेवा की जरूरत है):

class PeopleService 
{ 
    public async Task<Person> GetPersonByIdAsync(int id) 
    { 
     Person randomPerson = await DataContext.People.FirstOrDefaultAsync(x => x.Id == id); 
     return randomPerson; 
    } 
} 

आप अपनी सेवा देख सकते हैं अब async डेटाबेस के लिए कॉल करता है और कहा कि मूल रूप से क्या अपने पैटर्न चाहिए हो। आप इसे अपने सभी परिचालनों में जोड़ सकते हैं (जोड़ें/हटाएं/आदि ..)

अपनी सेवा को असीमित बनाने के बाद आपको आसानी से कार्रवाई में डेटा का उपभोग करने में सक्षम होना चाहिए।

[HttpGet("something")] 
public async Task<IActionResult> GetPerson(int id) 
{ 
    var result = await PeopleService.GetPersonByIdAsync(id); 

    if (result != null) 
     return Ok(result); 
    else 
     return NotFound("Role not found"); 
} 
+0

मैंने ef core async विधियों के बारे में थोड़ा सा शोध किया और कहा कि वे सिंक ef तरीकों से धीमे हैं .. कृपया सलाह दें। – krishna

+0

@kirshna Async विधियां धीमी हैं। उनके पास एक ओवरहेड है जो उन्हें सिंक्रनाइज़ करते समय अपरिहार्य है। लेकिन वे थ्रूपुट बढ़ा सकते हैं। इसलिए थ्रूपुट और प्रदर्शन दोनों के बीच संतुलन है जिस पर आपको विचार करना चाहिए। हमेशा प्रदर्शन प्रश्नों के बारे में सच है, यह जटिल है। https://www.dotnetrocks.com/?show=1433 इसे सुनें और आप देखेंगे कि मैं किस बारे में बात कर रहा हूं। – thinklarge

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