7

dispatch_apply() ब्लॉक में break कथन अनुकरण करने का कोई तरीका है?dispatch_apply() से "ब्रेक" कैसे करें?

जैसे, हर कोको एपीआई मैं गणना ब्लॉक के साथ देखा गया है निपटने के लिए एक "रोक" पैरामीटर है:

[array enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL *stop) { 
    if ([obj isNotVeryNice]) { 
     *stop = YES; // No more enumerating! 
    } else { 
     NSLog(@"%@ at %zu", obj, i); 
    } 
}]; 

वहाँ GCD के लिए कुछ इसी तरह है?

उत्तर

4

मैं dispatch_apply नहीं लगता कि यह समर्थन करता है। इसका अनुकरण करने का सबसे अच्छा तरीका यह है कि यह __block बूलियन वैरिएबल बनाना होगा, और ब्लॉक की शुरुआत में इसे जांचना होगा। यदि यह सेट है, तो जल्दी से जमानत। आपको अभी भी शेष पुनरावृत्तियों के माध्यम से ब्लॉक चलाना होगा, लेकिन यह तेज़ होगा।

1

आप कर सकते हैं break एक dispatch_apply के बाद से यह विसंगत है नहीं।

-enumerateObjectsUsingBlock: में एक ब्रेक अच्छी तरह से परिभाषित किया गया है क्योंकि फ़ंक्शन अनुक्रमिक रूप से चलाए जाते हैं। लेकिन dispatch_apply में फ़ंक्शंस समानांतर में चलाए जाते हैं। इसका अर्थ है "ब्लॉक" के i=3 के मुख्य आमंत्रण पर, i=4 वें कॉल शुरू हो सकता था। यदि आप पर i=3 पर हैं, तो i=4 कॉल अभी भी चलाना चाहिए?

@BJ के जवाब निकटतम आप क्या कर सकते हैं, लेकिन वहाँ हमेशा कुछ "गिर ओवर"।

+0

अच्छा, यह पूरी तरह से सच नहीं है; जबकि यह सच है कि enumerateObjectsUsingBlock: अनुक्रमिक है, वहाँ भी enumerateObjectsWithOptions है: का उपयोग कर ब्लॉक:। यह "विकल्प" पैरामीटर का उपयोग यह निर्देशित करने के लिए किया जा सकता है कि गणना समवर्ती रूप से होनी चाहिए। मुझे यकीन नहीं है कि वे आंतरिक रूप से ऐसा कैसे कर रहे हैं, लेकिन मुझे लगता है कि यह एक प्रेषण_ग्रुप का उपयोग करके किया गया है जो अधिक प्रत्यक्ष नियंत्रण की अनुमति देगा। –

+0

लेकिन बिंदु यह है कि enumerateObjectsWithOptions: useBlock: अभी भी * स्टॉप पैरामीटर है। –

+1

dispatch_apply() में रोकने का समर्थन करने के लिए यह तार्किक होगा, लेकिन यह डिजाइन लक्ष्यों के भीतर समझ में नहीं आया। यह बताते हुए कि 'enumerateObjectsUsingBlock पर स्टॉप फ्लैग:' अंतर्निहित अनुक्रमिक निष्पादन की वजह से मौजूद है; दोनों पूरी तरह से ऑर्थोगोनल हैं। – bbum

14

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

इस प्रकार, यदि आप "प्रारंभिक रोकना" चाहते हैं या अन्यथा प्रेषण कतार में लंबित आइटम को रद्द करना चाहते हैं (भले ही उन्हें कैसे लगाया गया हो), तो आप कुछ राज्यों को संलग्न ब्लॉक के साथ साझा करके ऐसा करते हैं जो आपको अनुमति देता है रद्द करना।

if (is_canceled()) return; 

या:

__block BOOL keepGoing = YES; 
dispatch_*(someQueue, ^{ 
    if (!keepGoing) return; 
    if (weAreDoneNow) keepGoing = NO; 
} 

ध्यान दें कि दोनों enumerateObjectsUsingBlock: और enumerateObjectsWithOptions:usingBlock: दोनों समर्थन रद्द क्योंकि कि एपीआई एक अलग भूमिका में है। गणना विधि के लिए कॉल तुल्यकालिक है, भले ही गणना करने वाले ब्लॉक का वास्तविक निष्पादन विकल्प के आधार पर पूरी तरह से समवर्ती हो।

इस प्रकार, *stopFlag=YES की स्थापना को रोकने के लिए गणन बताता है। हालांकि, यह गारंटी नहीं देता है कि यह समवर्ती मामले में तुरंत बंद हो जाएगा। वास्तव में, गणना रोकने से पहले कुछ और पहले से ही अवरुद्ध ब्लॉक निष्पादित कर सकते हैं।

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

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