Swift Language
संगामिति
खोज…
वाक्य - विन्यास
स्विफ्ट 3.0
DispatchQueue.main // मुख्य कतार प्राप्त करें
DispatchQueue (लेबल: "my-serial-queue", विशेषताएँ: [.serial, .qosBackground]) // अपनी निजी सीरियल कतार बनाएँ
DispatchQueue.global (विशेषताएं: [.qosDefault]) // वैश्विक समवर्ती कतारों में से एक पर पहुंचें
DispatchQueue.main.async {...} // कार्य को मुख्य धागे पर अतुल्य रूप से भेजना
DispatchQueue.main.sync {...} // किसी कार्य को मुख्य सूत्र में सिंक्रोनाइज़ करें
DispatchQueue.main.asyncAfter (समय सीमा: .now () + 3) {...} // एक्स के बाद निष्पादित होने के लिए मुख्य कार्य के लिए असिंक्रोनस रूप से किसी कार्य को डिस्पैच करें
स्विफ्ट <3.0
dispatch_get_main_queue () // मुख्य धागे पर चल रही मुख्य कतार प्राप्त करें
dispatch_get_global_queue (dispatch_queue_priority_t, 0) // निर्दिष्ट प्राथमिकता के साथ वैश्विक कतार प्राप्त करें dispatch_queue_priority_t
dispatch_async (dispatch_queue_t) {() -> शून्य में ...} // निर्दिष्ट डिस्पैच_queue_t पर एसिंक्रोनस रूप से कार्य को डिस्पैच करें
dispatch_sync (dispatch_queue_t) {() -> शून्य में ...} // निर्दिष्ट डिस्पैच_queue_t पर एक कार्य को सिंक्रोनाइज़ करें
dispatch_after (डिस्पैच_टाइम (DISPATCH_TIME_NOW, Int64 (नैनोसेकंड)), dispatch_queue_t, {...}); // नैनोसेकंड्स के बाद निर्दिष्ट प्रेषण_चेक_ टी पर एक कार्य को भेजें
ग्रांड सेंट्रल डिस्पैच (GCD) कतार प्राप्त करना
ग्रांड सेंट्रल डिस्पैच "डिस्पैच क्युस" की अवधारणा पर काम करता है। प्रेषण कतार आपके द्वारा निर्दिष्ट किए गए कार्यों को निष्पादित करती है, जो वे पारित किए जाते हैं। प्रेषण कतारों के तीन प्रकार हैं:
- सीरियल डिस्पैच क्यू (उर्फ निजी प्रेषण कतार) एक बार में एक कार्य को क्रम में निष्पादित करता है। वे अक्सर एक संसाधन तक पहुंच को सिंक्रनाइज़ करने के लिए उपयोग किए जाते हैं।
- समवर्ती डिस्पैच क्यू (उर्फ वैश्विक प्रेषण कतार) एक या एक से अधिक कार्यों को समवर्ती रूप से निष्पादित करते हैं।
- मुख्य डिस्पैच क्यू मुख्य धागे पर कार्यों को निष्पादित करता है।
मुख्य कतार तक पहुँचने के लिए:
let mainQueue = DispatchQueue.main
let mainQueue = dispatch_get_main_queue()
प्रणाली अलग-अलग प्राथमिकताओं के साथ समवर्ती वैश्विक प्रेषण कतार (आपके आवेदन के लिए वैश्विक) प्रदान करती है। आप स्विफ्ट 3 में DispatchQueue
वर्ग का उपयोग करके इन कतारों तक पहुँच सकते हैं:
let globalConcurrentQueue = DispatchQueue.global(qos: .default)
के बराबर
let globalConcurrentQueue = DispatchQueue.global()
let globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
आईओएस 8 या बाद में, सेवा मूल्यों की संभावित गुणवत्ता जो पारित की जा सकती है। .userInteractive
, .userInitiated
, .default
, .utility
और .background
। ये DISPATCH_QUEUE_PRIORITY_
स्थिरांक को प्रतिस्थापित करते हैं।
आप अलग-अलग प्राथमिकताओं के साथ अपनी खुद की कतार भी बना सकते हैं:
let myConcurrentQueue = DispatchQueue(label: "my-concurrent-queue", qos: .userInitiated, attributes: [.concurrent], autoreleaseFrequency: .workItem, target: nil)
let mySerialQueue = DispatchQueue(label: "my-serial-queue", qos: .background, attributes: [], autoreleaseFrequency: .workItem, target: nil)
let myConcurrentQueue = dispatch_queue_create("my-concurrent-queue", DISPATCH_QUEUE_CONCURRENT)
let mySerialQueue = dispatch_queue_create("my-serial-queue", DISPATCH_QUEUE_SERIAL)
स्विफ्ट 3 में, इस .workItem
के साथ बनाई गई कतारें डिफ़ॉल्ट रूप से धारावाहिक हैं, और गुजरता है। .workItem
आवृत्ति के लिए। .workItem
यह सुनिश्चित करता है कि प्रत्येक कार्य आइटम के लिए .workItem
पूल बनाया और सूखा हो। वहाँ भी है .never
जिसका मतलब है कि आप अपने आप को अपने स्वयं के autorelease पूल प्रबंध किया जाएगा, या, .inherit
जो वातावरण से सेटिंग को इनहेरिट करती। ज्यादातर मामलों में आप शायद का उपयोग नहीं होगा .never
चरम अनुकूलन के मामलों को छोड़कर।
ग्रैंड सेंट्रल डिस्पैच (जीसीडी) कतार में चल रहे कार्य
एक प्रेषण कतार पर कार्यों को चलाने के लिए, sync
, async
और तरीकों के after
उपयोग करें।
एक कार्य को असंगत रूप से एक कतार में भेजने के लिए:
let queue = DispatchQueue(label: "myQueueName")
queue.async {
//do something
DispatchQueue.main.async {
//this will be called in main thread
//any UI updates should be placed here
}
}
// ... code here will execute immediately, before the task finished
किसी कार्य को पंक्तिबद्ध तरीके से भेजने के लिए:
queue.sync {
// Do some task
}
// ... code here will not execute until the task is finished
कुछ सेकंड के बाद किसी कार्य को एक कतार में भेजने के लिए:
queue.asyncAfter(deadline: .now() + 3) {
//this will be executed in a background-thread after 3 seconds
}
// ... code here will execute immediately, before the task finished
नोट: उपयोगकर्ता-इंटरफ़ेस के किसी भी अपडेट को मुख्य धागे पर बुलाया जाना चाहिए! सुनिश्चित करें, कि आपने UI अपडेट के लिए कोड
DispatchQueue.main.async { ... }
अंदर डाल दिया है
कतार के प्रकार:
let mainQueue = dispatch_get_main_queue()
let highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
let backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
एक कार्य को असंगत रूप से एक कतार में भेजने के लिए:
dispatch_async(queue) {
// Your code run run asynchronously. Code is queued and executed
// at some point in the future.
}
// Code after the async block will execute immediately
किसी कार्य को पंक्तिबद्ध तरीके से भेजने के लिए:
dispatch_sync(queue) {
// Your sync code
}
// Code after the sync block will wait until the sync task finished
एक समय अंतराल के बाद किसी कार्य को भेजने के लिए ( NSEC_PER_SEC
का उपयोग कर सेकंड को नैनोसेकंड में परिवर्तित करें):
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
// Code to be performed in 2.5 seconds here
}
एसिंक्रोनस रूप से किसी कार्य को निष्पादित करने के लिए और UI अपडेट करने के लिए:
dispatch_async(queue) {
// Your time consuming code here
dispatch_async(dispatch_get_main_queue()) {
// Update the UI code
}
}
नोट: उपयोगकर्ता-इंटरफ़ेस के किसी भी अपडेट को मुख्य धागे पर बुलाया जाना चाहिए! सुनिश्चित करें, कि आपने UI अपडेट के लिए कोड
dispatch_async(dispatch_get_main_queue()) { ... }
अंदर डाल दिया है
समवर्ती लूप
जीसीडी एक लूप प्रदर्शन करने के लिए तंत्र प्रदान करता है, जिससे लूप एक दूसरे के संबंध में समवर्ती होते हैं। कम्प्यूटेशनल रूप से महंगी गणनाओं की श्रृंखला का प्रदर्शन करते समय यह बहुत उपयोगी है।
इस लूप पर विचार करें:
for index in 0 ..< iterations {
// Do something computationally expensive here
}
आप उन गणनाओं को समवर्ती concurrentPerform
(स्विफ्ट 3 में) या dispatch_apply
(स्विफ्ट 2 में) का उपयोग करके कर सकते हैं:
DispatchQueue.concurrentPerform(iterations: iterations) { index in
// Do something computationally expensive here
}
dispatch_apply(iterations, queue) { index in
// Do something computationally expensive here
}
लूप क्लोजर को प्रत्येक index
लिए 0
से लागू किया जाएगा, लेकिन iterations
शामिल नहीं किया जाएगा। इन पुनरावृत्तियों को एक दूसरे के संबंध में समवर्ती रूप से चलाया जाएगा, और इस प्रकार वे चलने वाले आदेश की गारंटी नहीं है। किसी भी समय समवर्ती रूप से होने वाली पुनरावृत्तियों की वास्तविक संख्या आमतौर पर प्रश्न में डिवाइस की क्षमताओं द्वारा निर्धारित की जाती है (जैसे कि डिवाइस में कितने कोर हैं)।
कुछ विशेष विचार:
concurrentPerform
/dispatch_apply
एक दूसरे के संबंध में समवर्ती छोरों को चला सकते हैं, लेकिन यह सब उस थ्रेड के संबंध में समकालिक रूप से होता है जहां से आप इसे कहते हैं। तो, इसे मुख्य धागे से न कहें, क्योंकि यह उस धागे को तब तक अवरुद्ध करेगा जब तक कि लूप नहीं हो जाता है।क्योंकि ये छोर एक दूसरे के संबंध में समवर्ती होते हैं, आप परिणामों की थ्रेड-सुरक्षा सुनिश्चित करने के लिए जिम्मेदार हैं। उदाहरण के लिए, यदि इन कम्प्यूटेशनल रूप से महंगी गणनाओं के परिणामों के साथ कुछ शब्दकोश अपडेट कर रहे हैं, तो उन अपडेट को स्वयं को सिंक्रनाइज़ करना सुनिश्चित करें।
ध्यान दें, समवर्ती छोरों को चलाने में जुड़े कुछ ओवरहेड हैं। इस प्रकार, यदि लूप के अंदर की जा रही गणना पर्याप्त रूप से गहन रूप से गहन नहीं है, तो आप पा सकते हैं कि समवर्ती छोरों का उपयोग करके प्राप्त किसी भी प्रदर्शन को कम किया जा सकता है, यदि पूरी तरह से ऑफसेट नहीं किया जाता है, तो इन सभी समवर्ती थ्रेड के सिंक्रनाइज़ेशन के साथ जुड़े ओवरहेड द्वारा।
तो, आप लूप के प्रत्येक पुनरावृत्ति में किए जाने वाले कार्य की सही मात्रा निर्धारित कर रहे हैं। यदि गणना बहुत सरल है, तो आप प्रति लूप में अधिक कार्य शामिल करने के लिए "स्ट्राइडिंग" को नियोजित कर सकते हैं। उदाहरण के लिए, 1 मिलियन तुच्छ गणनाओं के साथ समवर्ती लूप करने के बजाय, आप अपने लूप में 100 पुनरावृत्तियों कर सकते हैं, प्रति लूप 10,000 गणनाएं कर रहे हैं। इस तरह से प्रत्येक थ्रेड पर पर्याप्त कार्य किया जा रहा है, इसलिए इन समवर्ती छोरों के प्रबंधन से जुड़े ओवरहेड कम महत्वपूर्ण हो जाते हैं।
एक ऑपरेशन क्यू में चल रहे कार्य
आप किसी कार्य OperationQueue
एक पंक्ति के रूप में सोच सकते हैं जो निष्पादित होने की प्रतीक्षा कर रही है। जीसीडी में प्रेषण कतारों के विपरीत, ऑपरेशन कतार एफआईएफओ (पहले-पहले-बाहर) नहीं हैं। इसके बजाय, वे कार्यों को निष्पादित करते हैं जैसे ही वे निष्पादित करने के लिए तैयार होते हैं, जब तक कि इसके लिए अनुमति देने के लिए पर्याप्त सिस्टम संसाधन नहीं होते हैं।
मुख्य OperationQueue
प्राप्त करें:
let mainQueue = OperationQueue.main
एक कस्टम OperationQueue
बनाएँ:
let queue = OperationQueue()
queue.name = "My Queue"
queue.qualityOfService = .default
सेवा की गुणवत्ता कार्य के महत्व को निर्दिष्ट करती है, या उपयोगकर्ता को कार्य से तत्काल परिणाम पर गिनने की कितनी संभावना है।
एक Operation
में एक OperationQueue
जोड़ें:
// An instance of some Operation subclass
let operation = BlockOperation {
// perform task here
}
queue.addOperation(operation)
किसी OperationQueue
लिए एक ब्लॉक जोड़ें:
myQueue.addOperation {
// some task
}
एक OperationQueue
कई Operation
जोड़ें:
let operations = [Operation]()
// Fill array with Operations
myQueue.addOperation(operations)
समायोजित करें कि कितने Operation
s कतार के भीतर समवर्ती चलाए जा सकते हैं:
myQueue.maxConcurrentOperationCount = 3 // 3 operations may execute at once
// Sets number of concurrent operations based on current system conditions
myQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount
एक कतार को निलंबित करने से इसे किसी भी मौजूदा, बिना ऑपरेशन के या कतार में जोड़े गए किसी भी नए संचालन का निष्पादन शुरू करने से रोका जा सकेगा। इस कतार को फिर से शुरू करने का तरीका यह है कि वापस false
को सेट किया isSuspended
:
myQueue.isSuspended = true
// Re-enable execution
myQueue.isSuspended = false
एक OperationQueue
निलंबित करना उन कार्यों को रोकना या रद्द करना नहीं है जो पहले से ही निष्पादित हो रहे हैं। केवल एक कतार को निलंबित करने का प्रयास करना चाहिए जिसे आपने बनाया है, न कि वैश्विक कतार या मुख्य कतार।
उच्च-स्तरीय संचालन बनाना
फाउंडेशन फ्रेमवर्क Operation
प्रकार प्रदान करता है, जो एक उच्च-स्तरीय ऑब्जेक्ट का प्रतिनिधित्व करता है जो कार्य के एक हिस्से को कूटबद्ध करता है जिसे एक कतार में निष्पादित किया जा सकता है। न केवल कतार उन कार्यों के प्रदर्शन को समन्वित करती है, बल्कि आप संचालन के बीच निर्भरता भी स्थापित कर सकते हैं, रद्द करने योग्य संचालन बना सकते हैं, ऑपरेशन कतार द्वारा नियोजित संगामिति की डिग्री को बाधित कर सकते हैं, आदि।
Operation
तब निष्पादित करने के लिए तैयार हो जाता है जब उसके सभी आश्रित निष्पादन को समाप्त कर देते हैं। isReady
प्रॉपर्टी तब true
बदलती true
।
एक साधारण गैर-समवर्ती Operation
उपवर्ग बनाएं:
class MyOperation: Operation {
init(<parameters>) {
// Do any setup work here
}
override func main() {
// Perform the task
}
}
class MyOperation: NSOperation {
init(<parameters>) {
// Do any setup work here
}
override func main() {
// Perform the task
}
}
एक ऑपरेशन में एक OperationQueue
जोड़ें:
myQueue.addOperation(operation)
यह कतार पर समवर्ती रूप से संचालन को निष्पादित करेगा।
एक Operation
पर निर्भरता की व्यवस्था करें।
निर्भरताएँ अन्य Operation
s को परिभाषित करती हैं जिन्हें पहले एक कतार में निष्पादित किया जाना चाहिए इससे पहले कि Operation
को निष्पादित करने के लिए तैयार माना जाता है।
operation2.addDependency(operation1)
operation2.removeDependency(operation1)
एक कतार के बिना एक Operation
चलाएं:
operation.start()
निर्भरता को नजरअंदाज किया जाएगा। यदि यह एक समवर्ती ऑपरेशन है, तब भी कार्य को समवर्ती रूप से निष्पादित किया जा सकता है यदि इसकी start
विधि ऑफ़लोड पृष्ठभूमि कतारों में काम करती है।
समवर्ती संचालन।
यदि वह कार्य जो एक Operation
को करना है, स्वयं, अतुल्यकालिक है, (जैसे URLSession
डेटा कार्य), तो आपको Operation
को समवर्ती Operation
रूप में लागू करना चाहिए। इस स्थिति में, आपका isAsynchronous
क्रियान्वयन true
होना चाहिए, आपके पास आम तौर पर start
विधि होगी जो कुछ सेटअप करती है, फिर इसकी main
विधि को कॉल करती है जो वास्तव में कार्य को निष्पादित करती है।
जब एक अतुल्यकालिक Operation
को लागू करना शुरू होता है तो आपको लागू करना आवश्यक होता है। isExecuting
, isFinished
तरीके और isFinished
। इसलिए, जब निष्पादन शुरू होता है, isExecuting
संपत्ति में परिवर्तन true
जाता true
। जब कोई Operation
अपना कार्य पूरा करता है, तो isExecuting
को false
सेट किया जाता false
, और isFinished
को true
सेट किया जाता true
। आपरेशन यदि यह दोनों रद्द कर दिया गया isCancelled
और isFinished
करने के लिए परिवर्तन true
। ये सभी गुण मुख्य-माननीय हैं।
एक Operation
रद्द करें।
कॉलिंग cancel
बस isCancelled
प्रॉपर्टी true
बदल जाती true
। अपने स्वयं के Operation
उपवर्ग के भीतर से रद्द करने का जवाब देने के लिए, आपको समय-समय पर main
से कम से कम और उचित रूप से जवाब में अलग- isCancelled
के मूल्य की जांच करनी चाहिए।
operation.cancel()