2013-02-04 10 views
5

मेरे पास एक छवि लोडर वर्ग है जो वेब से NSURL लोड और छवि प्रदान करता है और पूर्णता ब्लॉक निष्पादित करता है। कोड वास्तव में काफी सरलजीसीडी और बहुत सारे धागे के साथ समस्या

- (void)downloadImageWithURL:(NSString *)URLString completion:(BELoadImageCompletionBlock)completion 
{ 
    dispatch_async(_queue, ^{ 
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
     UIImage *image = nil; 
     NSURL *URL = [NSURL URLWithString:URLString]; 
     if (URL) { 
      image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]]; 
     } 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      completion(image, URLString); 
     }); 
    }); 

}

जब मैं की जगह

dispatch_async(_queue, ^{ 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 

छवियाँ बाहर टिप्पणी की साथ बहुत तेजी से लोड कर रहे हैं है, जो काफी तार्किक है (कि पहले छवियों को एक समय में लोड किया जाएगा, अब उनमें से एक गुच्छा एक साथ लोड हो रहे हैं)। मेरी समस्या यह है कि मेरे पास शायद 50 छवियां हैं और मैं डाउनलोड करता हूं IMageWithURL: समापन: उन सभी के लिए विधि और जब मैं अपने ऐप के बजाय वैश्विक कतार का उपयोग करता हूं तो अंततः क्रैश हो जाता है और मुझे लगता है कि 85+ धागे हैं। क्या समस्या यह हो सकती है कि मेरी कॉलिंग dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0) पंक्ति में 50 बार जीसीडी बहुत सारे धागे बना देती है? मैंने सोचा कि जीसीडी सभी चलने को संभालता है और सुनिश्चित करता है कि धागे की संख्या बड़ी नहीं है, लेकिन यदि ऐसा नहीं है तो क्या कोई तरीका है कि मैं धागे की संख्या को प्रभावित कर सकता हूं?

उत्तर

2
खैर http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

समवर्ती कतारों (यह भी एक प्रकार के रूप में जाना जाता है से

वैश्विक प्रेषण कतार का) एक या एक से अधिक कार्यों को एक साथ निष्पादित करें, लेकिन कार्य अभी भी में शुरू किए गए क्रम में वे जोड़े गए थे कतार में एड। वर्तमान में प्रेषण कतार द्वारा प्रबंधित किए गए अलग-अलग थ्रेड पर चलने वाले कार्यों को निष्पादित करते हैं। किसी दिए गए बिंदु पर निष्पादित कार्यों की सटीक संख्या परिवर्तनीय है और सिस्टम स्थितियों पर निर्भर करती है।

और

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

[NSData dataWithContentsOfURL:URL] 

जो एक तुल्यकालिक अवरुद्ध नेटवर्क आपरेशन है के साथ उच्च प्राथमिकता समवर्ती प्रेषण कतार में अपने सभी ब्लॉक भेजने करके, यह डिफ़ॉल्ट GCD व्यवहार की तरह लग रहा करने के लिए सूत्र का भार अंडे देने के लिए किया जाएगा अपने ब्लॉक ASAP निष्पादित करें।

आपको DISPATCH_QUEUE_PRIORITY_BACKGROUND पर प्रेषण होना चाहिए। ये कार्य किसी भी तरह से "उच्च प्राथमिकता" नहीं हैं। जब कोई खाली समय होता है और मुख्य धागे पर कुछ भी नहीं हो रहा है तो कोई भी छवि प्रसंस्करण किया जाना चाहिए।

यदि आप एक बार में इनमें से कितनी चीजें हो रही हैं, इस पर अधिक नियंत्रण चाहते हैं तो मुझे लगता है कि आप NSOperation का उपयोग करने में लग रहे हैं। आप अपने ब्लॉक ले सकते हैं और उन्हें NSBlockOperation का उपयोग करके एक ऑपरेशन में एम्बेड कर सकते हैं और फिर आप इन परिचालनों को अपने NSOperationQueue पर सबमिट कर सकते हैं। एक NSOperationQueue में - (NSInteger)maxConcurrentOperationCount है और यदि आवश्यक हो तो शेड्यूलिंग के बाद अतिरिक्त लाभ संचालन भी रद्द कर दिया जा सकता है।

+4

नहीं, इसका कतार प्राथमिकता से कोई लेना-देना नहीं है। जीसीडी केवल अतिरिक्त थ्रेड बनाता है जब कर्नेल में वैश्विक समवर्ती कतार ब्लॉक के लिए मौजूदा थ्रेड पर अवरुद्ध होता है। – das

+0

@ दास धन्यवाद मैंने कुछ संपादन किए हैं लेकिन कृपया मेरा उत्तर भी बेहतर बनाने के लिए स्वतंत्र महसूस करें :) – jackslash

1

आप NSOperationqueue, जिसके द्वारा NSURLConnection

समर्थित है का उपयोग कर सकते और यह निम्नलिखित उदाहरण विधि है:

- (void)setMaxConcurrentOperationCount:(NSInteger)count 
8

गिरी अतिरिक्त धागे से उत्पन्न होने वाला एक वैश्विक समवर्ती कतार के लिए मौजूदा GCD कार्यकर्ता धागे पर कार्य इकाइयां समय की एक महत्वपूर्ण राशि के लिए कर्नेल में ब्लॉक किए गए हैं (जब तक वहाँ आगे काम वैश्विक कतार पर लंबित है)।

यह आवश्यक है ताकि एप्लिकेशन समग्र रूप से प्रगति कर सके (उदाहरण के लिए लंबित ब्लॉक में से एक का निष्पादन अवरुद्ध धागे को अनब्लॉक करने की अनुमति देता है)।

कार्यकर्ता धागे के लिए कारण कर्नेल में अवरुद्ध होने हैं आईओ (जैसे इस उदाहरण में +[NSData dataWithContentsOfURL:]) है, सबसे अच्छा समाधान एक API के साथ उन कॉल की जगह है कि आईओ एसिंक्रोनस रूप से अवरूद्ध किए बिना, उदा प्रदर्शन करेंगे है फाइल सिस्टम IO के लिए नेटवर्किंग या प्रेषण I/O के लिए NSURLConnection

वैकल्पिक रूप से आप समवर्ती अवरुद्ध संचालन की संख्या को मैन्युअल रूप से सीमित कर सकते हैं, उदा। एक गिनती प्रेषण semaphore का उपयोग करके।

WWDC 2012 जीसीडी सत्र कुछ विस्तार से इस विषय पर चला गया।

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