मुख्य सूत्र में कार्य करने के लिए जीसीडी


255

मेरे पास एक कॉलबैक है जो किसी भी थ्रेड से आ सकता है। जब मुझे यह कॉलबैक मिलेगा, तो मैं मुख्य थ्रेड पर एक निश्चित कार्य करना चाहूंगा।

क्या मुझे यह जांचने की आवश्यकता है कि क्या मैं पहले से ही मुख्य धागे पर हूं - या क्या नीचे दिए गए कोड को कॉल करके इस चेक befora का प्रदर्शन नहीं करने से कोई जुर्माना है?

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here
});

117
पांच साल बाद भी मुझे जीसीडी ब्लॉक का सिंटैक्स याद नहीं आ रहा है और हर बार यहीं खत्म हो जाता है।
स्पेसट्रूकर

7
@SpaceTrucker - यही कारण है कि मैं इस पृष्ठ पर हूँ: D
मैथ्यू Cawley

4
9 साल बाद, और मैं अब भी इस पृष्ठ से वाक्य रचना की नकल करने आता हूं।
ओसा

जवाबों:


153

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

यदि आप पहले से ही मुख्य धागे पर हैं, तो व्यवहार समान है: ब्लॉक अनुसूचित है, और निष्पादित किया जाता है जब मुख्य धागे का रन लूप चलाया जाता है।


3
सवाल यह था कि क्या "इस चेक को न करने से जुर्माना" है ... मुझे लगता है कि एसिंक्स प्रेषण का उपयोग करने के लिए एक प्रदर्शन जुर्माना है जब यह आवश्यक नहीं है, या क्या यह तुच्छ है?
दान रोसेनस्टार्क

1
@ यार मुझे नहीं लगता कि ज्यादातर मामलों में ध्यान देने योग्य प्रदर्शन प्रभाव है: जीसीडी एक हल्का पुस्तकालय है। उस ने कहा, मैं इस प्रश्न को समझ गया: 'नीचे दिए गए कोड को, क्या मुझे यह जांचने की आवश्यकता है कि क्या मैं मुख्य धागे पर हूं?'

7
हालाँकि, आपको यह जाँचने की आवश्यकता है कि क्या आप डिस्पैच_संकल्प का उपयोग करते हैं। अन्यथा आपको गतिरोध मिल जाता है।
विक्टर एंगेल

यदि आप मुख्य कतार में हैं और मुख्य कतार asyncपर वापस भेजते हैं , तो इसे चलाया जाएगा लेकिन यह आपके कार्यों की अपेक्षित समय को गड़बड़ कर सकता है । जैसे कि यूआई कोड पहले प्रदर्शित viewDidLoad() होने के बाद तक चलने में नहीं
पीकेएम

106

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

हालाँकि, यदि आप उपरोक्त का उपयोग करने का प्रयास करते हैं dispatch_sync()और आपका कॉलबैक मुख्य धागे पर है, तो आपका आवेदन उसी बिंदु पर गतिरोध करेगा। मैं यहां अपने उत्तर में इसका वर्णन करता हूं , क्योंकि इस व्यवहार ने मुझे आश्चर्यचकित किया जब कुछ कोड को आगे बढ़ाया -performSelectorOnMainThread:। जैसा कि मैंने वहाँ उल्लेख किया है, मैंने एक सहायक समारोह बनाया:

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

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

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

1
इसे "runOnMainQueueSync" की तरह क्यों न कहें? तथ्य यह है कि यह गतिरोध कर सकता है और इस तरह की बात नहीं है जो मैं अपने कोड पर नहीं करना चाहता हूं। हमेशा की तरह धन्यवाद और +1।
डैन रोसेनस्टार्क

2
@ यार - मैंने इसे सिर्फ यह नाम दिया ताकि मेरे लिए यह स्पष्ट हो जाए कि मैं इस हेल्पर फ़ंक्शन का उपयोग करने के बजाय मुख्य कतार पर समान रूप से ब्लॉक से फायरिंग क्यों नहीं कर रहा था। यह अपने आप को याद दिलाने वाला था।
ब्रैड लार्सन

3
इस फ़ंक्शन के साथ गतिरोध अभी भी संभव है। मुख्य-कतार सिंक> अन्य-कतार सिंक> मुख्य-कतार गतिरोध।
21

2
@hfossli - सच है, यह हर मामले को संभाल नहीं होगा। मेरे उपयोग में, मैं हमेशा या तो मुख्य धारा पर एक पृष्ठभूमि धारावाहिक कतार या इनलाइन कोड पर एक अतुल्यकालिक प्रेषण से बुला रहा था। मुझे आश्चर्य है कि अगर dispatch_set_specific()आप इस मामले का वर्णन करने में मदद करेंगे: stackoverflow.com/a/12806754/19679
ब्रैड लार्सन

1
[NSThreadMainThread है] अक्सर YES देता है और GCD प्रोग्रामिंग में इस मामले की जाँच के लिए सुरक्षित नहीं माना जाता है। stackoverflow.com/questions/14716334/…
लार्च

57

जैसा कि उल्लेखित अन्य उत्तर हैं, मुख्य धागे से डिस्पैच_सुंक ठीक है।

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

उदाहरण के लिए,

NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");

प्रिंट आउट निकालेंगे:

before dispatch async
after dispatch async
inside dispatch async block main thread from main thread

इस कारण से, यदि आप बाहरी NSLog's के बीच ब्लॉक को निष्पादित करने की उम्मीद कर रहे थे, तो डिस्पैच_संक आपकी मदद नहीं करेगा।


कहने की जरूरत है कि यह एक महत्वपूर्ण बात है
मार्क-एलेक्जेंडर बेयरुबे

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

1

नहीं, अगर आपको मुख्य सूत्र में होने की जाँच करने की आवश्यकता नहीं है। यहाँ आप स्विफ्ट में ऐसा कैसे कर सकते हैं:

runThisInMainThread { () -> Void in
    runThisInMainThread { () -> Void in
        // No problem
    }
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

मेरे रेपो में इसका मानक कार्य शामिल है, इसे देखें : https://github.com/goktugyil/EZSwiftExtensions

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.