c# - कई कार्यों के लिए async/प्रतीक्षा का उपयोग करना




.net task-parallel-library (3)

मैं एक एपीआई क्लाइंट का उपयोग कर रहा हूं जो पूरी तरह से असीमित है, यानी, प्रत्येक ऑपरेशन या तो Task या Task<T> , उदाहरण के लिए:

static async Task DoSomething(int siteId, int postId, IBlogClient client)
{
    await client.DeletePost(siteId, postId); // call API client
    Console.WriteLine("Deleted post {0}.", siteId);
}

सी # 5 async / ऑपरेटरों का इंतजार कर रहे हैं, एकाधिक कार्यों को शुरू करने के लिए सही / सबसे प्रभावी तरीका क्या है और उन सभी को पूरा करने का इंतजार करें:

int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());

या:

int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());

चूंकि एपीआई क्लाइंट आंतरिक रूप से एचटीपी क्लाइंट का उपयोग कर रहा है, इसलिए मैं उम्मीद करता हूं कि यह तुरंत 5 HTTP अनुरोध जारी करेगी, कंसोल को लिखकर प्रत्येक व्यक्ति पूरा करेगा।


आप कार्य का उपयोग कर सकते हैं। जब आप सभी कार्यों को पारित कर सकते हैं; कार्य। जब सभी कार्य को पूरा कर देंगे जो पूरा करने के लिए चलता है जब आप कार्य को पारित किए गए सभी कार्यों को पूरा करते हैं। जब पूरा हो जाएगा। आपको कार्य पर Task.WhenAll रूप से इंतजार करना होगा। जब भी आप अपने यूआई थ्रेड को अवरुद्ध नहीं करेंगे:

   public async Task DoSomeThing() {

       var Task[] tasks = new Task[numTasks];
       for(int i = 0; i < numTask; i++)
       {
          tasks[i] = CallSomeAsync();
       }
       await Task.WhenAll(tasks);
       // code that'll execute on UI thread
   }

चूंकि आप जिस एपीआई को कॉल कर रहे हैं वह एसिंक है, Parallel.ForEachParallel.ForEach संस्करण ज्यादा समझ में नहीं आता है। आपको उपयोग नहीं करना WaitAllWaitAll संस्करण में WaitAll क्योंकि इससे समांतरता खो जाएगी एक और विकल्प अगर कॉलर ToArray है तो कार्य का सरणी उत्पन्न करने के लिए Select और ToArray करने के बाद। दूसरा विकल्प आरएक्स 2.0 का उपयोग कर रहा है


int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());

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

int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());

दूसरी तरफ, WaitAll के साथ उपरोक्त कोड धागे को भी अवरुद्ध करता है और ऑपरेशन समाप्त होने तक आपके धागे किसी अन्य काम को संसाधित करने के लिए स्वतंत्र नहीं होंगे।

अनुशंसित दृष्टिकोण

मैं WhenAll पसंद WhenAll जो समानांतर में आपके परिचालन को WhenAll से निष्पादित करेगा।

public async Task DoWork() {

    int[] ids = new[] { 1, 2, 3, 4, 5 };
    await Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}

असल में, उपर्युक्त मामले में, आपको await करने की भी आवश्यकता नहीं है, आप सीधे विधि से वापस आ सकते हैं क्योंकि आपके पास कोई निरंतरता नहीं है:

public Task DoWork() 
{
    int[] ids = new[] { 1, 2, 3, 4, 5 };
    return Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}

इसे वापस करने के लिए, यहां एक विस्तृत ब्लॉग पोस्ट सभी विकल्पों और उनके फायदे / नुकसान के माध्यम से जा रहा है: ASP.NET वेब API के साथ समवर्ती असिंक्रोनस I / O कैसे और कहाँ





c#-5.0