45

मैंने दोनों जीसीडी और प्रदर्शन चयनकर्ता ओनमेन थ्रेड का उपयोग किया है: मेरे ऐप्स में प्रतीक्षा करें, और इन्हें अदला-बदले के रूप में सोचने के लिए प्रवृत्त हैं - यानी, प्रदर्शनकर्ता चयन करें: प्रतीक्षा करें कोई भी ओब्ज नहीं है जीसीडी सी वाक्यविन्यास के लिए सीसी रैपर। मैं इन दो आदेशों के बराबर सोच रहा हूं:ग्रैंड सेंट्रल डिस्पैच (जीसीडी) बनाम प्रदर्शन चयनकर्ता - एक बेहतर स्पष्टीकरण की आवश्यकता है

dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; }); 


[self performSelectorOnMainThread:@selector(doit:) withObject:YES waitUntilDone:YES]; 

क्या मैं गलत हूं? यही है, क्या जीसीडी बनाम प्रदर्शन चयनकर्ता * कमांड का कोई अंतर है? मैंने उन पर बहुत सारे दस्तावेज पढ़े हैं, लेकिन अभी तक एक निश्चित उत्तर नहीं देखा है।

+5

साथ ऑब्जेक्ट: हाँ काम नहीं करेगा और आपको कम से कम एक चेतावनी देना चाहिए। जो जीडीसी का एक फायदा हो सकता है, जहां आप रिसीवर को मनमाने ढंग से तर्क भेज सकते हैं। – FelixLam

+0

ठीक है, मुझे इसे एनएसएनंबर में लपेटना होगा। लेकिन, उस हिस्से को अनदेखा करते हुए, कुछ और अलग है? अच्छा बिंदु, यद्यपि। – akaru

उत्तर

20

performSelectorOnMainThread: मुख्य थ्रेड पर ऑब्जेक्ट्स को संदेश भेजने के लिए जीसीडी का उपयोग नहीं करता है।

यहाँ documentation कैसे कहते हैं विधि कार्यान्वित किया जाता है:

- (void) performSelectorOnMainThread:(SEL) selector withObject:(id) obj waitUntilDone:(BOOL) wait { 
    [[NSRunLoop mainRunLoop] performSelector:selector target:self withObject:obj order:1 modes: NSRunLoopCommonModes]; 
} 

और performSelector:target:withObject:order:modes: पर, प्रलेखन राज्यों:

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

65

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

मैं हाल ही में इसमें भाग गया, जहां मेरे पास एक आम तरीका था जो कभी-कभी मुख्य धागे पर कुछ से चलाया जाता था, कभी-कभी नहीं। कुछ यूआई अपडेटों की सुरक्षा के लिए, मैं बिना किसी समस्या के -performSelectorOnMainThread: का उपयोग कर रहा था।

जब मैंने मुख्य कतार पर dispatch_sync का उपयोग करने के लिए स्विच किया, तो जब भी यह विधि मुख्य कतार पर चलती थी तो एप्लिकेशन डेडलॉक हो जाएगा। dispatch_sync पर दस्तावेज़ीकरण पढ़ना, हम देखते हैं:

इस कार्यप्रणाली को कॉल और लक्षित कर गतिरोध में वर्तमान कतार परिणाम नहीं।

जहां -performSelectorOnMainThread: के लिए हम देखते हैं

इंतजार

एक बूलियन कि निर्दिष्ट करती है कि जब तक के बाद निर्दिष्ट चयनकर्ता मुख्य थ्रेड पर रिसीवर पर किया जाता है वर्तमान धागा ब्लॉक । इस धागे को ब्लॉक करने के लिए हाँ निर्दिष्ट करें; अन्यथा, यह विधि तुरंत वापस करने के लिए निर्दिष्ट करें।

वर्तमान धागा भी मुख्य धागा है, और आप इस पैरामीटर के लिए हाँ निर्दिष्ट करते हैं, संदेश दिया और तुरंत संसाधित किया जाता है।

मैं अभी भी GCD की शान पसंद करते हैं, बेहतर संकलन समय की जाँच यह प्रदान करता है, और इसके लिए अधिक से अधिक तर्क, आदि के बारे में लचीलापन, तो मैं गतिरोध को रोकने के लिए इस छोटे सहायक समारोह बनाया:

void runOnMainQueueWithoutDeadlocking(void (^block)(void)) 
{ 
    if ([NSThread isMainThread]) 
    { 
     block(); 
    } 
    else 
    { 
     dispatch_sync(dispatch_get_main_queue(), block); 
    } 
} 

अद्यतन: डेव ड्रिबिन के जवाब में caveats section ondispatch_get_current_queue() को इंगित करते हुए, मैं उपरोक्त कोड में [NSThread isMainThread] का उपयोग करने के लिए बदल गया हूं।

मैं तो

runOnMainQueueWithoutDeadlocking(^{ 
    //Do stuff 
}); 

का उपयोग क्या थ्रेड मूल विधि पर मार डाला गया था के बारे में चिंता किए बिना, कार्यों मैं मुख्य थ्रेड पर सुरक्षित करने के लिए की जरूरत करने के लिए।

+1

@ जो- मुख्य प्रेषण के लिए 'dispatch_sync()' अभी भी आपके आवेदन के भीतर एक डेडलॉक का कारण बन सकता है यदि मुख्य थ्रेड पर कुछ आपके पृष्ठभूमि थ्रेड ('dispatch_sync() 'या कुछ और के माध्यम से) के मूल्य पर प्रतीक्षा कर रहा था। यह बहुत ही असंभव है, लेकिन अभी भी संभव है। यह दो धागे की मानक थ्रेडिंग समस्या है जो दूसरे को कुछ करने की प्रतीक्षा कर रही है, इसलिए कुछ भी नहीं किया जाता है। –

+0

@ जो - हाँ, अगर आप पूरी तरह से गैर-मुख्य कतार या धागे पर चल रहे हैं, तो आपको ऊपर दिए गए कोड की आवश्यकता नहीं है। मैंने जो डेडलॉक मुद्दा अभी उल्लेख किया है, वह भी इस कोड के साथ एक समस्या होगी। यह एक वास्तुशिल्प मुद्दा है। जहां तक ​​टिप्पणियां जाती हैं, इस मेटा प्रश्न को देखें: http://meta.stackexchange.com/questions/43019/how-do-comment-replies-work। –

+11

पेडेंट्री ओवरफ़्लो: आप 'dispatch_block_t' का उपयोग तर्क प्रकार के रूप में बदसूरत 'शून्य (^ ब्लॉक) (शून्य)' के रूप में कर सकते हैं। –

1

जीसीडी का तरीका संभालने के लिए अधिक कुशल और आसान होने का अनुमान है और केवल आईओएस 4 में उपलब्ध है जबकि प्रदर्शन चयनकर्ता पुराने और नए आईओएस में समर्थित है।

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

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