डिस्पैच_संकल्प को समझना


233

मेरे पास इस कोड के बारे में प्रश्न है

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData* data = [NSData dataWithContentsOfURL: 
      kLatestKivaLoansURL];
    [self performSelectorOnMainThread:@selector(fetchedData:) 
      withObject:data waitUntilDone:YES];
});

इस कोड का पहला पैरामीटर है

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

क्या हम इस कोड को वैश्विक कतार में धारावाहिक कार्य करने के लिए कह रहे हैं, जिसकी परिभाषा स्वयं यह है कि यह किसी दिए गए प्राथमिकता स्तर की वैश्विक समवर्ती कतार लौटाता है?

dispatch_get_global_queueमुख्य कतार पर उपयोग करने से क्या फायदा है ?

मैं उलझन में हूं। क्या आप मुझे इसे बेहतर समझने में मदद कर सकते हैं।


1
आपको अपने कोड को बेहतर तरीके से कई पंक्तियों में काट देना चाहिए ताकि इसका अधिक अर्थ हो सके। dispatch_get_global_queueएक चर प्रकार के अंदर अपने को सुरक्षित करें dispatch_queue_t myQueue। इसके अधिक पठनीय केवल myQueue को आपके `` dispatch_async` पास करना
एलेक्स Cio

जवाबों:


517

मुख्य कारण आप मुख्य कतार पर डिफ़ॉल्ट कतार का उपयोग करते हैं, पृष्ठभूमि में कार्यों को चलाने के लिए है।

उदाहरण के लिए, यदि मैं इंटरनेट से कोई फ़ाइल डाउनलोड कर रहा हूं और मैं डाउनलोड की प्रगति पर उपयोगकर्ता को अपडेट करना चाहता हूं, तो मैं प्राथमिकता डिफ़ॉल्ट कतार में डाउनलोड चलाऊंगा और यूआई को मुख्य रूप से अतुल्यकालिक रूप से अपडेट करूंगा।

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

मैं समझता हूं कि आपके उत्तर के लिए बहुत धन्यवाद, लेकिन मेरा सवाल यह करने के तर्क को समझने के लिए अधिक था, अर्थात यह कोड वैश्विक कतार पर धारावाहिक कार्यों को करने के लिए कह रहा है जो कि समवर्ती कतार है
user2332873

मैं बिल्कुल वही कर रहा हूं जो आप सुझाते हैं लेकिन किसी भी तरह से, uiTableViewCell एकदम सही नहीं चलता है, जब मैं रन यूआई अपडेट में [self.tableView reloadData] कहता हूं। इसमें लगभग 4 या 5 सेकंड लगते हैं। यह कई दिनों से पागल हो रहा है। ।
ग्रैंडस्टेप

@GrandSteph मैं उस विधि से बहुत परिचित नहीं हूँ। हो सकता है कि उस विधि को चलाने के लिए सिर्फ 5 सेकंड लगते हैं। Dispatch_async के साथ महत्वपूर्ण बात यह है कि यह आपको मुख्य थ्रेड को लटकाए बिना पृष्ठभूमि में चीजें करने की अनुमति देता है।
डेविड

2
क्या 0संकेत देता है?
Honey

3
@ हनी द 0 flagsपैरामीटर है, जो वर्तमान में बिल्कुल कुछ भी नहीं करता है। डॉक्स से:Flags that are reserved for future use. Always specify 0 for this parameter.
डेविड

199

DISPATCH_QUEUE_PRIORITY_X कतार में से सभी समवर्ती कतारें हैं (जिसका अर्थ है कि वे एक साथ कई कार्यों को निष्पादित कर सकते हैं), और FIFO इस अर्थ में हैं कि किसी दिए गए कतार के भीतर कार्य "पहले, पहले बाहर" क्रम का उपयोग करके निष्पादित करना शुरू कर देंगे। यह मुख्य कतार (dispatch_get_main_queue () से) की तुलना में है, जो एक सीरियल कतार है (कार्य उस क्रम में निष्पादित और समाप्त करना शुरू कर देंगे जिसमें वे प्राप्त होते हैं)।

इसलिए, यदि आप DISPATCH_QUEUE_PRIORITY_DEFAULT को 1000 प्रेषण_सुंक () ब्लॉक भेजते हैं, तो वे कार्य आपके द्वारा कतार में भेजे गए क्रम में निष्पादित होने लगेंगे। इसी तरह हाई, लो और बैकग्राउंड कतारों के लिए। इन कतारों में आप जो भी भेजते हैं, वह आपके मुख्य एप्लिकेशन थ्रेड से दूर, वैकल्पिक थ्रेड पर पृष्ठभूमि में निष्पादित होता है। इसलिए, ये कतारें पृष्ठभूमि डाउनलोडिंग, संपीड़न, गणना, आदि जैसे कार्यों को निष्पादित करने के लिए उपयुक्त हैं।

ध्यान दें कि निष्पादन का क्रम प्रति पंक्ति के आधार पर FIFO है। इसलिए यदि आप चार अलग-अलग समवर्ती कतारों में 1000 प्रेषण_संकट () कार्य भेजते हैं, तो समान रूप से उन्हें विभाजित करें और उन्हें BACKGROUND, LOW, DEFAULT और HIGH के क्रम में भेजें (यानी आप उच्च कतार पर अंतिम 250 कार्य शेड्यूल करते हैं), यह बहुत संभावना है कि पहला कार्य जो आप देख रहे हैं, वह उस उच्च कतार पर होगा क्योंकि सिस्टम ने आपके निहितार्थ को ले लिया है कि उन कार्यों को जितनी जल्दी हो सके सीपीयू में लाने की आवश्यकता है।

यह भी ध्यान दें कि मैं कहता हूं कि "क्रम में क्रियान्वयन शुरू हो जाएगा", लेकिन ध्यान रखें कि समवर्ती कतारों के रूप में आवश्यक रूप से प्रत्येक कार्य के लिए समय की लंबाई के आधार पर निष्पादित करना आवश्यक नहीं होगा।

Apple के अनुसार:

https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

समवर्ती प्रेषण कतार उपयोगी है जब आपके पास कई कार्य हैं जो समानांतर में चल सकते हैं। एक समवर्ती कतार अभी भी एक कतार है जिसमें यह पहले-पहले, पहले-क्रम में कार्यों को समाप्त करता है; हालाँकि, एक समवर्ती कतार किसी भी पिछले कार्य को पूरा करने से पहले अतिरिक्त कार्यों को समाप्त कर सकती है। किसी भी समय एक समवर्ती कतार द्वारा निष्पादित कार्यों की वास्तविक संख्या परिवर्तनशील होती है और आपके एप्लिकेशन परिवर्तन की स्थितियों में गतिशील रूप से बदल सकती है। कई कारक समवर्ती कतारों द्वारा निष्पादित कार्यों की संख्या को प्रभावित करते हैं, जिनमें उपलब्ध कोर की संख्या, अन्य प्रक्रियाओं द्वारा किए जा रहे कार्य की मात्रा और अन्य सीरियल प्रेषण कतारों में कार्यों की संख्या और प्राथमिकता शामिल है।

मूल रूप से, यदि आप उन 1000 प्रेषण_सुंक () ब्लॉक को एक DEFAULT, HIGH, LOW, या BACKGROUND कतार में भेजते हैं तो वे सभी आपके द्वारा भेजे जाने वाले क्रम में क्रियान्वित होने लगेंगे। हालाँकि, छोटे कार्य अधिक समय से पहले समाप्त हो सकते हैं। इसके पीछे कारण यह हैं कि यदि उपलब्ध सीपीयू कोर हैं या यदि वर्तमान कतार के कार्य कम्प्यूटेशनल रूप से गैर-गहन कार्य कर रहे हैं (इस प्रकार सिस्टम को लगता है कि यह कोर काउंट की परवाह किए बिना समानांतर में अतिरिक्त कार्यों को भेज सकता है)।

समसामयिकता का स्तर पूरी तरह से सिस्टम द्वारा नियंत्रित किया जाता है और सिस्टम लोड और अन्य आंतरिक रूप से निर्धारित कारकों पर आधारित होता है। यह ग्रैंड सेंट्रल डिस्पैच (डिस्पैच_सुंक () सिस्टम) की सुंदरता है - आप बस अपनी कार्य इकाइयों को कोड ब्लॉक बनाते हैं, उनके लिए प्राथमिकता तय करते हैं (आपके द्वारा चुनी गई कतार के आधार पर) और सिस्टम को बाकी को संभालने दें।

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

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


+1, लेकिन मुझे लगता है कि व्यवहार में यह बहुत मायने नहीं रखता है कि समवर्ती कतारें FIFO हैं या केवल यादृच्छिक क्रम। यदि आप एक लूप में 5 कार्य शुरू करते हैं, तो मान लें कि वे अनिवार्य रूप से एक ही समय में शुरू करेंगे। इस बात की कोई गारंटी नहीं है कि 1 कार्य का पहला I / O ऑपरेशन 5 वीं से पहले होगा, भले ही वे एक ही कोड निष्पादित करें। OTOH, धारावाहिक कतारों के लिए, FIFO व्यवहार आवश्यक है और IMHO यह दो कतार प्रकारों के बीच का अंतर है।
गेरहार्ड वेस्प

अविश्वसनीय व्याख्या। बहुत ताली बजाता है!
ओखेन ओक्बे

36

स्विफ्ट संस्करण

यह डेविड के उद्देश्य-सी उत्तर का स्विफ्ट संस्करण है। आप यूआई को अपडेट करने के लिए पृष्ठभूमि और मुख्य कतार में चीजों को चलाने के लिए वैश्विक कतार का उपयोग करते हैं।

DispatchQueue.global(qos: .background).async {
    
    // Background Thread
    
    DispatchQueue.main.async {
        // Run UI Updates
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.