c# - क्या आपको कार्य को एसिंक बनाने के लिए एक विधि में रखना है?




.net-4.5 async-await (2)

जब आप किसी विधि को चलाने के लिए कार्य। Run का उपयोग करते हैं, तो कार्य को उस विधि को चलाने के लिए थ्रेडपूल से धागा मिलता है। तो यूआई थ्रेड के परिप्रेक्ष्य से, यह "असीमित" है क्योंकि यह यूआई थ्रेड को अवरुद्ध नहीं करता है। यह डेस्कटॉप एप्लिकेशन के लिए ठीक है क्योंकि आपको आमतौर पर उपयोगकर्ता इंटरैक्शन की देखभाल करने के लिए कई धागे की आवश्यकता नहीं होती है।

हालांकि, वेब एप्लिकेशन के लिए प्रत्येक अनुरोध को थ्रेड-पूल थ्रेड द्वारा सर्विस किया जाता है और इस तरह ऐसे धागे को सहेजकर सक्रिय अनुरोधों की संख्या में वृद्धि की जा सकती है। एसिंक ऑपरेशन अनुकरण करने के लिए अक्सर थ्रेडपूल धागे का उपयोग वेब अनुप्रयोगों के लिए स्केलेबल नहीं है।

सही Async जरूरी नहीं है कि I / O संचालन के लिए थ्रेड का उपयोग करना शामिल हो, जैसे फ़ाइल / डीबी एक्सेस इत्यादि। आप यह समझने के लिए पढ़ सकते हैं कि I / O ऑपरेशन को थ्रेड की आवश्यकता क्यों नहीं है। http://blog.stephencleary.com/2013/11/there-is-no-thread.html

आपके सरल उदाहरण में, यह एक शुद्ध सीपीयू-बाध्य गणना है, इसलिए कार्य का उपयोग करना। रुन ठीक है।

मैं एसिंक को सबसे सरल रूप में प्रतीक्षा करने की कोशिश कर रहा हूं। मैं एक बहुत ही सरल विधि बनाना चाहता हूं जो इस उदाहरण के लिए दो संख्याओं को जोड़ती है, दी गई है, यह कोई प्रसंस्करण समय नहीं है, यह सिर्फ एक उदाहरण तैयार करने का मामला है।

उदाहरण 1

private async Task DoWork1Async()
{
    int result = 1 + 2;
}

उदाहरण 2

private async Task DoWork2Async()
{
    Task.Run( () =>
    {
        int result = 1 + 2;
    });
}

अगर मैं DoWork1Async() इंतजार करता DoWork1Async() तो कोड सिंक्रनाइज़ या DoWork1Async() ?

क्या मुझे सिंक कोड को Task.Run के साथ लपेटने की ज़रूरत है। विधि को प्रतीक्षा करने योग्य और अतुल्यकालिक बनाने के लिए ताकि UI थ्रेड को अवरुद्ध न किया जा सके?

मैं यह पता लगाने की कोशिश कर रहा हूं कि मेरी विधि कोई Task या Task<T> वापस आती है Task<T> क्या मुझे Task<T> के साथ कोड को लपेटने की आवश्यकता है। इसे अतुल्यकालिक बनाने के लिए।

बेवकूफ सवाल मुझे यकीन है, लेकिन मैं नेट पर उदाहरण देखता हूं जहां लोग ऐसे कोड का इंतजार कर रहे हैं जिसमें कार्य में लपेटा नहीं गया है और कार्य में लपेटा नहीं गया है। Task.Run या StartNew


सबसे पहले, आइए कुछ शब्दावली साफ़ करें: "एसिंक्रोनस" ( async ) का अर्थ यह है कि इससे पहले कॉलिंग थ्रेड पर नियंत्रण शुरू हो सकता है। एक async विधि में, उन "उपज" अंक अभिव्यक्ति का await कर रहे हैं।

यह "एसिंक्रोनस" शब्द से बहुत अलग है, जैसा कि (गलत) एमएसडीएन दस्तावेज द्वारा वर्षों से "पृष्ठभूमि धागे पर निष्पादित" का अर्थ है।

इस मुद्दे को भ्रमित करने के लिए, async "प्रतीक्षा करने योग्य" से बहुत अलग है; कुछ async विधियां हैं जिनके रिटर्न प्रकार इंतजार नहीं कर रहे हैं, और कई तरीकों से प्रतीक्षा करने योग्य प्रकार लौट रहे हैं जो एसिंक नहीं हैं।

वे क्या नहीं हैं के बारे में पर्याप्त है; यहां वे हैं जो हैं :

  • async कीवर्ड एक एसिंक्रोनस विधि (यानी, यह await अभिव्यक्ति की अनुमति देता है) की अनुमति देता है। async विधियां Task , Task<T> , या (यदि आपको जरूरी हो) void
  • कोई भी प्रकार जो एक निश्चित पैटर्न का पालन करता है, वह प्रतीक्षा कर सकता है। सबसे आम प्रतीक्षा प्रकार Task और Task<T>

इसलिए, अगर हम आपके प्रश्न को " पृष्ठभूमि थ्रेड पर एक ऑपरेशन कैसे चला सकते हैं जिस तरह से यह इंतजार कर रहा है" में सुधार करने के लिए, जवाब का उपयोग करना है। Task.Run :

private Task<int> DoWorkAsync() // No async because the method does not need await
{
  return Task.Run(() =>
  {
    return 1 + 2;
  });
}

(लेकिन यह पैटर्न एक खराब दृष्टिकोण है; नीचे देखें)।

लेकिन अगर आपका सवाल है "मैं एक async विधि कैसे बना सकता हूं जो अवरोध करने के बजाए अपने कॉलर पर वापस आ सकता है", तो जवाब विधि async को घोषित करना है और इसके "उपज" बिंदुओं के लिए await करना है:

private async Task<int> GetWebPageHtmlSizeAsync()
{
  var client = new HttpClient();
  var html = await client.GetAsync("http://www.example.com/");
  return html.Length;
}

इसलिए, चीजों का मूल पैटर्न async कोड को अपने await अभिव्यक्तियों में " await " पर निर्भर await है। ये "प्रतीक्षा" अन्य async विधियां हो सकती हैं या केवल प्रतीक्षा विधियों को प्रतीक्षा कर सकती हैं। Task / Task<T> लौटने वाले नियमित तरीके Task<T> पृष्ठभूमि थ्रेड पर कोड निष्पादित करने के लिए Task<T> उपयोग कर सकते हैं, या (अधिक सामान्यतः) वे TaskCompletionSource<T> या इसके शॉर्टकट्स ( TaskFactory.FromAsync , Task.FromResult , आदि) का उपयोग कर सकते हैं। । मैं कार्य में पूरी विधि को लपेटने की अनुशंसा नहीं करता Task.RunTask.Run ; तुल्यकालिक तरीकों में तुल्यकालिक हस्ताक्षर होना चाहिए, और इसे उपभोक्ता को छोड़ दिया जाना चाहिए चाहे उसे कार्य में लपेटा जाना चाहिए। Task.Run :

private int DoWork()
{
  return 1 + 2;
}

private void MoreSynchronousProcessing()
{
  // Execute it directly (synchronously), since we are also a synchronous method.
  var result = DoWork();
  ...
}

private async Task DoVariousThingsFromTheUIThreadAsync()
{
  // I have a bunch of async work to do, and I am executed on the UI thread.
  var result = await Task.Run(() => DoWork());
  ...
}

मेरे पास मेरे ब्लॉग पर एक async / await परिचय है ; अंत में कुछ अच्छे अनुवर्ती संसाधन हैं। एसिंक के लिए एमएसडीएन दस्तावेज़ असामान्य रूप से भी अच्छे हैं।





c#-5.0