2012-06-08 24 views
14

क्या NSoperationQueue ऑब्जेक्ट को maxConcurrentOperationCount से 1 सेट करके एक सीरियल फीफो कतार के रूप में उपयोग करना संभव है?NSOperationQueue सीरियल फीफो कतार

मैं ध्यान दें कि docs राज्य ...

एक कतार जिसका अधिकतम समवर्ती आपरेशनों की संख्या 1 पर सेट है के लिए, यह एक सीरियल कतार के बराबर है। हालांकि, आपको ऑपरेशन ऑब्जेक्ट्स के धारावाहिक निष्पादन पर कभी भरोसा नहीं करना चाहिए।

क्या इसका मतलब यह है कि फीफो निष्पादन की गारंटी नहीं है?

उत्तर

23

ज्यादातर मामलों में, यह फीफो होगा। हालांकि, आप NSOperations के बीच निर्भरताओं को स्थापित कर सकते हैं जैसे कि पहले से प्रस्तुत एक ऑपरेशन अन्य परिचालनों को कतार में तब तक पारित कर देगा जब तक कि इसकी निर्भरता संतुष्ट न हों।

यह निर्भरता प्रबंधन यही कारण है कि दस्तावेज़ बताते हैं कि फीफो-नेस की गारंटी नहीं दी जा सकती है। यदि आप निर्भरताओं का उपयोग नहीं कर रहे हैं, हालांकि, आप पर भरोसा करना ठीक होना चाहिए।

अद्यतन: NSOperation भी एक queuePriority संपत्ति है, जो भी संचालन गैर फीफो क्रम में निष्पादित करने के लिए पैदा कर सकता है है। कोई लंबित निर्भरता वाले सर्वोच्च प्राथमिकता संचालन हमेशा पहले निष्पादित होगा।

एनएसओपरेशन सबक्लास भी -isReady को ओवरराइड कर सकता है, जो इसे कतार में वापस ले जाने का कारण बन सकता है।

तो आपकी कतार पर निष्पादन धारावाहिक होने की गारंटी है, जिसमें इस कतार में एक से अधिक ऑपरेशन नहीं चलेंगे। लेकिन ऐप्पल फीफो की गारंटी नहीं दे सकता; कि क्या आप आपरेशनों आप में डाल के साथ कर रहे हैं पर निर्भर करता है

+0

निष्पादन के आदेश भी आपरेशन की कतार प्राथमिकता के आधार पर निर्भर करता है। – JeremyP

+0

बहुत सच है। अपडेट किया गया। –

+0

तो यदि मेरे परिचालनों की सभी प्राथमिकताएं हैं, तो कोई निर्भरता नहीं है और केवल 'isReady' (मैं ओवरराइड नहीं करता) के सुपरक्लस कार्यान्वयन पर भरोसा करता हूं, जिसके परिणामस्वरूप फीफो कतार होनी चाहिए? – Barjavel

-2

nsInvocationopration का उपयोग कर एक सरल फीफो बनाने के लिए आप एक आपरेशन सेट करने की आवश्यकता होगी addDependency का उपयोग अन्य पर निर्भर होने के लिए:। विधि

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
NSInvocationOperation *oper1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"1"]; 

NSInvocationOperation *oper2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"2"]; 
NSInvocationOperation *oper3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"3"]; 

[oper2 addDependency:oper1]; 
[oper3 addDependency:oper2]; 
//oper3 depends on oper2 wich depends on oper1 
//order of execution will ber oper1->oper2->oper3 

//Changing the oreder will not change the result 
[queue addOperation:oper2]; 
[queue addOperation:oper3]; 
[queue addOperation:oper1]; 


- (void) doSth:(NSString*)str 
{ 
    NSLog(str); //log will be 1 2 3 
    //When you remove the addDependency calls, the logging result that i got where 
    //different between consecutive runs i got the following 
    //NSLog(str); //log will be 2 1 3 
    //NSLog(str); //log will be 3 1 2 
} 

नोट: यदि आप NSInvocationOperation उपयोग कर रहे हैं तो स्थापित करने maxConcurrentOperationCount 1 करने के लिए सबसे अधिक संभावना है आप के लिए चाल, isReady के बाद से नहीं आप

लेकिनसंपादित कर सकेगा करते हैं= 1 एक अच्छा समाधान आप के बाद से NSOperation

की अपनी खुद की उपवर्गों बनाने NSOperation डेरिवेटिव में आप isReady समारोह को ओवरराइड और वापसी कर सकता है कोई, (कुछ कार्रवाई से कुछ डेटा इंतजार करने की आवश्यकता होगी कल्पना करना रंदा कर रहे हैं नहीं होगा करने के लिए एक सर्वर आदेश इन मामलों में ठीक ढंग से काम करने के लिए) आप isReady no वापसी होगी जब तक आप वास्तव में तैयार इन मामलों में आप कतार

अंदर operations के बीच dependencies जोड़ने के लिए सेब डॉक्स इस एक सीरियल कतार के बराबर से की आवश्यकता होगी रहे हैं में । हालांकि, आपको ऑपरेशन ऑब्जेक्ट्स के धारावाहिक निष्पादन पर कभी भरोसा नहीं करना चाहिए। ऑपरेशन की तत्परता में परिवर्तन परिणामस्वरूप निष्पादन आदेश

+0

क्या आप समझा सकते हैं कि निर्भरता क्यों आवश्यक है? –

+0

@BJHomer मैंने कुछ लॉगिंग –

+0

को शामिल करने के लिए अपना उत्तर अपडेट किया है उदाहरण में आपकी कतार में 'maxConcurrentOperationCount = 1' निर्दिष्ट ओपी की तरह नहीं है। क्या यह अभी भी उस सेट के साथ होता है? –

12

कतार दस्तावेज द्वारा उल्लिखित फीफो नहीं है।यदि आप सुनिश्चित करते हैं कि कोई नया ऑपरेशन कतार में जोड़े गए अंतिम ऑपरेशन पर निर्भर करता है और यह एक समय में केवल एक ही ऑपरेशन चला सकता है तो आप इसे सख्ती से फीफो बना सकते हैं। उमर समाधान सही है, लेकिन अधिक आम तौर पर, आप निम्न कर सकते हैं:

NSOperationQueue* queue = [[ NSOperationQueue alloc ] init]; 
queue.maxConcurrentOperationCount = 1; 

NSOperation* someOperation = [ NSBlockOperation blockOperationWithBlock:^(void) { NSLog(@"Done.");} ]; 

if (queue.operations.count != 0) 
    [ someOperation addDependency: queue.operations.lastObject ]; 

यह काम करता है क्योंकि queue.operations एक सरणी है: जो भी आप जोड़ने पुनर्क्रमित नहीं है (यह उदाहरण के लिए एक NSSet नहीं है)। तुम भी बस अपने NSOperationQueue के एक वर्ग जोड़ सकते हैं:

@interface NSOperationQueue (FIFOQueue) 
- (void) addOperationAfterLast:(NSOperation *)op; 
@end 

@implementation NSOperationQueue (FIFOQueue) 

- (void) addOperationAfterLast:(NSOperation *)op 
{ 
    if (self.maxConcurrentOperationCount != 1) 
     self.maxConcurrentOperationCount = 1; 

    NSOperation* lastOp = self.operations.lastObject; 
    if (lastOp != nil) 
     [ op addDependency: lastOp ]; 

    [ self addOperation:op]; 
} 

@end 

और प्रयोग [कतार addOperationAfterLast: myOperation]। कतार प्राथमिकता फीफो के साथ कुछ लेना देना नहीं है, यह नौकरी शेड्यूलिंग से संबंधित है।

संपादित करें: नीचे दी गई टिप्पणी के बाद, कतार को निलंबित करने पर कतार को निलंबित करना पर्याप्त नहीं है। मेरा मानना ​​है कि यह फॉर्म ठीक है (परीक्षण पर, यह दौड़ की स्थिति नहीं बनाता है और क्रैश नहीं होता है)।

कुछ जानकारी: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/#//apple_ref/occ/instp/NSOperationQueue/suspended

+0

इस प्रकार के समाधान में कोई समस्या है। मैं इसका इस्तेमाल कर रहा हूँ। कभी-कभी, queue.operations.count पर चेक के बाद कतार का अंतिम ऑब्जेक्ट गायब हो जाएगा। यह दुर्लभ है, लेकिन ऐसा होता है। और मुझे यकीन नहीं है कि इसे कैसे हल किया जाए। –

+0

अच्छा बिंदु मैंने इसे नहीं देखा लेकिन हां: यदि कतार चलने के दौरान ऑपरेशन.count की जांच की जाती है, तो यह समाप्त हो सकता है जब हम स्थिति में प्रवेश कर रहे हों। मेरा मानना ​​है कि संपादित फॉर्म बेहतर और सुरक्षित है: (यहां परीक्षण क्रैश नहीं होते हैं, जबकि कतार को निलंबित करने का प्रयास काम नहीं करता है (दिखाया नहीं गया है)। – Daniel

+0

यही वह समाधान है जो मैं भी आया था; एनएसओपरेशन को रिहा होने से रोकते हुए स्थानीय चर बनाओ। –