DispatchQueue.main.async और DispatchQueue.main.sync के बीच अंतर


99

मैं DispatchQueue.main.asyncयूआई से संबंधित संचालन करने के लिए लंबे समय से उपयोग कर रहा हूं ।



स्विफ्ट दोनों प्रदान करता है DispatchQueue.main.asyncऔर DispatchQueue.main.sync, और दोनों मुख्य कतार में किए जाते हैं।



क्या कोई मुझे उनके बीच का अंतर बता सकता है? मुझे प्रत्येक का उपयोग कब करना चाहिए?



DispatchQueue.main.async {
    self.imageView.image = imageView
    self.lbltitle.text = ""

}

DispatchQueue.main.sync {
    self.imageView.image = imageView
    self.lbltitle.text = ""
}

जवाबों:


45

जब आप इसका उपयोग asyncकरते हैं, तब तक प्रतीक्षा किए बिना कॉलिंग कतार चलती रहती है जब तक कि प्रेषण ब्लॉक निष्पादित नहीं हो जाता। इसके विपरीत syncकॉलिंग कतार बंद हो जाएगी और तब तक प्रतीक्षा करें जब तक कि ब्लॉक में आपके द्वारा भेजा गया काम पूरा नहीं हो जाता। इसलिए syncगतिरोध का नेतृत्व करने के लिए विषय है। DispatchQueue.main.syncमुख्य कतार से चलने का प्रयास करें और ऐप फ्रीज़ हो जाएगा क्योंकि कॉलिंग कतार तब तक प्रतीक्षा करेगी जब तक कि प्रेषण ब्लॉक समाप्त नहीं हो जाता है, लेकिन यह प्रारंभ भी नहीं कर पाएगा (क्योंकि कतार बंद हो गई है और प्रतीक्षा कर रहा है)

कब करें इस्तेमाल sync? जब आपको किसी अलग कतार में कुछ करने की प्रतीक्षा करनी पड़े और उसके बाद ही अपनी वर्तमान कतार पर काम करना जारी रखें

सिंक का उपयोग करने का उदाहरण:

एक सीरियल कतार पर आप syncम्यूटेक्स के रूप में उपयोग कर सकते हैं ताकि यह सुनिश्चित हो सके कि केवल एक धागा एक ही समय में कोड के संरक्षित टुकड़े का प्रदर्शन करने में सक्षम है।


क्या DispatchQueue.main.syncबैकग्राउंड थ्रेड से कॉल करना गलत होगा ?
हनी

@ सामान्य रूप से, इस तरह की कॉल के साथ कुछ भी गलत नहीं है (जब तक कि मुख्य कतार कुछ भी भारी और समय लेने वाली नहीं है), लेकिन व्यवहार में मैं ऐसी स्थिति के बारे में नहीं सोच सकता जहां आपको वास्तव में इसकी आवश्यकता है। निश्चित रूप से एक बेहतर समाधान होना चाहिए
एंड्री चेर्नुखा

1
@ इस तरह की स्थिति PhotoKit API से PHAssets के कलेक्शन व्यू को अपडेट कर रही है, जैसा कि यहाँ प्रलेखन में दिखाया गया है: developer.apple.com/documentation/photokit/…
teacup

1
@ दिलचस्प। मैं सोच रहा हूं कि अगर हम asyncवहां बुलाएंगे तो यह कैसे अलग होगा? मेरा मतलब है कि बाद में धागे पर और कुछ नहीं है तो इससे कोई फर्क नहीं पड़ता। अगर DispatchQueue.main.sync {block1}; DispatchQueue.main.sync {block2};होता तो समझ में आता। लेकिन जब कोई दूसरा ब्लॉक नहीं होता है तो मैं DispatchQueue.main.sync {Oneblock}ओवर के इस्तेमाल के फायदे के बारे में नहीं सोच सकता DispatchQueue.main.async {Oneblock}। उन दोनों के लिए उन्हें मेनक्यू प्राथमिकता / immediacy मिलेगी और कुछ भी उन्हें बाधित नहीं करेगा।
हनी

3
@ "जब से थ्रेड पर और कुछ नहीं है" तब तक सही नहीं है जब आप मुख्य थ्रेड पर हैं, जो ऐप के साथ सभी उपयोगकर्ता इंटरैक्शन से निपटने के लिए जिम्मेदार है। इसलिए, उदाहरण के लिए, उपयोगकर्ता किसी अन्य फोटो को हटा सकता है इससे पहले कि PhotoLibraryDidChange अपडेट किए गए डेटा स्रोत के साथ एक घातक असंगतता त्रुटि के साथ वापस आ जाए।
चायपत्ती

160

चिंता क्यों?

जैसे ही आप अपने ऐप में भारी कार्य जोड़ते हैं, जैसे डेटा लोड करना यह आपके यूआई काम को धीमा कर देता है या इसे जमा देता है। Concurrency आपको 2 या अधिक कार्य "एक साथ" करने देता है। इस दृष्टिकोण का नुकसान यह है कि धागा सुरक्षा जो नियंत्रण के लिए हमेशा आसान नहीं होती है। Fe जब अलग-अलग कार्य एक ही संसाधनों को एक्सेस करना चाहते हैं जैसे कि एक अलग वेरिएबल पर एक ही वेरिएबल को बदलने की कोशिश करना या अलग-अलग थ्रेड द्वारा पहले से ब्लॉक किए गए संसाधनों तक पहुंचना।

कुछ सार हैं जिनसे हमें अवगत होने की आवश्यकता है।

  • कतार।
  • तुल्यकालिक / अतुल्यकालिक कार्य प्रदर्शन।
  • प्राथमिकताएं।
  • आम परेशानियाँ।

कतार

सीरियल या समवर्ती होना चाहिए । साथ ही साथ वैश्विक या निजी भी

धारावाहिक कतारों के साथ, कार्यों को एक-एक करके समाप्त किया जाएगा, जबकि समवर्ती कतारों के साथ, कार्यों को एक साथ किया जाएगा और अप्रत्याशित शेड्यूल पर समाप्त किया जाएगा। समवर्ती कतार की तुलना में कार्यों का एक ही समूह धारावाहिक कतार पर अधिक समय लेगा।

आप अपनी निजी कतारें बना सकते हैं ( धारावाहिक या समवर्ती दोनों ) या पहले से उपलब्ध वैश्विक (सिस्टम) कतारों का उपयोग कर सकते हैंमुख्य कतार केवल है धारावाहिक कतार के सभी से बाहर वैश्विक कतारों

यह उन भारी कार्यों को नहीं करने के लिए अत्यधिक अनुशंसित है, जो यूआई काम को मुख्य कतार (नेटवर्क से फ़्ल लोडिंग डेटा) पर संदर्भित नहीं करते हैं , बल्कि यूआई को अनफ्रेंड और उपयोगकर्ता कार्यों के लिए उत्तरदायी रखने के लिए अन्य कतारों पर करते हैं। यदि हम यूआई को अन्य कतारों में परिवर्तित होने देते हैं, तो परिवर्तन एक अलग और अप्रत्याशित अनुसूची और गति पर किए जा सकते हैं। कुछ UI तत्वों को उनकी आवश्यकता से पहले या बाद में खींचा जा सकता है। यह यूआई को क्रैश कर सकता है। हम यह भी है कि जब से ध्यान में रखने की जरूरत है वैश्विक कतारों हैं प्रणाली कतारों वहाँ कुछ अन्य कार्यों के लिए उन पर प्रणाली द्वारा चलाए जा सकते हैं।

सेवा की गुणवत्ता / प्राथमिकता

कतार भी अलग है QoS (सेवा की गुणवत्ता) जो कार्य सेट प्राथमिकता (उच्चतम से न्यूनतम करने के लिए यहाँ):
.userInteractive - मुख्य कतार
.userInitiated - उपयोगकर्ता द्वारा आरंभ किए कार्यों के लिए, जिस पर कुछ प्रतिक्रिया के लिए उपयोगकर्ता प्रतीक्षा करता है
.utility - कार्यों के लिए जो कुछ समय लगता है और तत्काल प्रतिक्रिया, जैसे डेटा के साथ काम करने की आवश्यकता नहीं है
.background - कार्यों के लिए जो दृश्य भाग के साथ संबंधित नहीं हैं और जिसके लिए पूरा होने के समय के लिए सख्त नहीं हैं)। .Default क्यू

भी है जो qos जानकारी को स्थानांतरित नहीं करता है। यदि qos का पता लगाना संभव नहीं था

qos का उपयोग .userInitiated और .utility के बीच किया जाएगा ।

कार्य समकालिक या असिंक्रोनस रूप से किए जा सकते हैं ।

  • कार्य समाप्त होने के बाद ही सिंक्रोनस फ़ंक्शन वर्तमान कतार में नियंत्रण लौटाता है। यह कतार को अवरुद्ध करता है और कार्य समाप्त होने तक प्रतीक्षा करता है।

  • असिंक्रोनस फ़ंक्शन कार्य को अलग-अलग कतार पर प्रदर्शन करने के लिए भेजे जाने के तुरंत बाद वर्तमान कतार पर नियंत्रण लौटाता है। यह कार्य पूरा होने तक प्रतीक्षा नहीं करता है। यह कतार को अवरुद्ध नहीं करता है।

आम परेशानियाँ।

सबसे लोकप्रिय गलतियाँ प्रोग्रामर करते हैं, जबकि समवर्ती ऐप्स को प्रोजेक्ट करना निम्नलिखित हैं:

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

कभी भी मुख्य पंक्ति पर सिंक फ़ंक्शन को कॉल न करें
यदि आप मुख्य कतार में सिंक फ़ंक्शन को कॉल करते हैं, तो यह कतार को अवरुद्ध कर देगा और साथ ही कतार कार्य के पूरा होने की प्रतीक्षा कर रही होगी लेकिन कार्य कभी भी समाप्त नहीं होगा क्योंकि यह कतार के कारण शुरू करने में सक्षम नहीं होगा। पहले से ही अवरुद्ध है। इसे गतिरोध कहा जाता है ।

सिंक का उपयोग कब करें? जब हमें कार्य समाप्त होने तक इंतजार करना होगा। Fe जब हम यह सुनिश्चित कर रहे हैं कि कुछ फ़ंक्शन / विधि डबल नहीं है। Fe का हमारे पास सिंक्रोनाइज़ेशन है और इसे तब तक रोकने की कोशिश की जा रही है जब तक कि यह पूरी तरह से समाप्त न हो जाए। इस चिंता के लिए यहां कुछ कोड दिया गया है:
IOS डिवाइस पर त्रुटि क्रैश रिपोर्ट का कारण क्या है?


3
मुझे नहीं लगता कि "कभी भी मुख्य कतार पर सिंक फ़ंक्शन को कॉल न करें" सही है। ऐसे मामले हैं जब आप उदाहरण के लिए मुख्य थ्रेड में सिंक को कॉल करेंगे जब आपके पास एक वैश्विक काउंटर होगा जिसे आपको उपयोग करने और बढ़ाने के लिए प्रत्येक ऑब्जेक्ट की आवश्यकता है: dispatchQueue.sync {count + = 1; self.orderId = count}
एलिशा स्टर्नगॉल्ड

6
QOS क्लास - .userInteractive मुख्य कतार नहीं है।
कुणाल शाह

1
क्या DispatchQueue.main.syncबैकग्राउंड थ्रेड से कॉल करना गलत होगा ?
हनी

1
@ नहीं, यह गलत नहीं है कि कॉल करें लेकिन मेरे अनुभव से, आपको लगता है कि आप अपने आप को DispatchQueue.main.async से अधिक कॉल करेंगे।
जेम्स किम

2
क्या यह कहना अधिक सटीक नहीं होगा कि आपको वर्तमान कतार पर सिंक () फ़ंक्शन को कभी नहीं कॉल करना चाहिए? अगर मैं सही तरीके से समझूं, तो दूसरी कतार में मुख्य पंक्ति पर सिंक () को कॉल करना गलत नहीं है।
23

0

syncया asyncविधियों का उस कतार पर कोई प्रभाव नहीं पड़ता है जिस पर उन्हें बुलाया जाता है।

syncधागा को अवरुद्ध कर देगा से जो यह कहा जाता है और नहीं है कतार पर जो यह कहा जाता है। यह संपत्ति है DispatchQueueजो यह तय करती है कि क्या DispatchQueueकार्य निष्पादन (धारावाहिक कतार) की प्रतीक्षा करेगा या वर्तमान कार्य समाप्त होने से पहले अगला कार्य चला सकता है (समवर्ती कतार)।

इसलिए जब DispatchQueue.main.asyncभी एक एसिंक्स कॉल होता है, तो इसमें जोड़ा गया एक भारी शुल्क ऑपरेशन यूआई को फ्रीज कर सकता है क्योंकि इसके संचालन को मुख्य धागे पर क्रमिक रूप से निष्पादित किया जाता है। यदि इस विधि को पृष्ठभूमि थ्रेड से कहा जाता है, तो नियंत्रण यूआई के जमे हुए होने पर भी तुरंत उस थ्रेड पर वापस आ जाएगा। ऐसा इसलिए है क्योंकि asyncकॉल किया जाता हैDispatchQueue.main


0

GCDआप एक कार्य synchronouslyया asynchronously[के बारे में] निष्पादित करने की अनुमति देता है [अधिक]

synchronous(ब्लॉक एंड वेट) फ़ंक्शन एक नियंत्रण लौटाता है जब कार्य पूरा हो जाएगा

asynchronous(प्रेषण और आगे बढ़ना) फ़ंक्शन तुरंत एक नियंत्रण लौटाता है, कार्य को एक उचित कतार में शुरू करने के लिए भेज रहा है लेकिन इसके पूरा होने की प्रतीक्षा नहीं कर रहा है।

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