2011-09-07 3 views
9

NSOperation के लिए [NSOperationQueue currentQueue] या [NSThread currentThread] के बराबर है?वर्तमान में निष्पादित NSOperation को कैसे पकड़ें?

मेरे पास एक काफी जटिल डोमेन मॉडल है जहां भारी स्टैक कॉल स्टैक में काफी गहराई से होता है। एक ऑपरेशन को समय पर रद्द करने के लिए मुझे NSOperation को प्रत्येक विधि के पैरामीटर के रूप में पास करने की आवश्यकता होगी जब तक कि मैं उस बिंदु तक नहीं पहुंच जाता जहां मैं लंबे समय तक चलने वाले लूप को बाधित करना चाहता हूं। धागे का उपयोग करके मैं [[NSThread currentThread] isCancelled] का उपयोग कर सकता हूं, इसलिए यदि एनएसओपरेशन के बराबर है तो यह सुविधाजनक लगेगा, दुर्भाग्यवश केवल उबाऊ [NSOperationQueue currentQueue] है।

उत्तर

3

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

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

आप वास्तव में क्या करने की कोशिश कर रहे हैं? यही कारण है कि, आपको लगता है कि आपके ऐप के अन्य हिस्सों को सीधे वर्तमान ऑपरेशन के बारे में जानने की आवश्यकता क्यों है?

+0

-1 मुझे डर लग रहा। इनमें से कोई भी काम करने जा रहा है। ऑपरेशन की स्थापना करना रद्द की गई संपत्ति का कोई प्रभाव नहीं पड़ेगा जब तक कि ऑपरेशन समय-समय पर रद्द की गई संपत्ति की जांच न करे। निश्चित रूप से केवीओ काम नहीं करेगा क्योंकि केवीओ अधिसूचनाएं उसी धागे पर प्राप्त की जाती हैं जिन्हें वे भेजे जाते हैं। – JeremyP

+3

एरर ... क्या आपने इसे नीचे पोस्ट करने से पहले अपनी पोस्ट पढ़ी? इन गुणों का निरीक्षण करना * बिल्कुल * ये चीजें कैसे की जाती हैं। आप मुख्य परिवर्तन पर करने की आवश्यकता वाले कुछ भी करने के लिए राज्य परिवर्तन का उपयोग करते हैं, फिर -फॉर्म चयनकर्ताऑनमेन थ्रेड ... का उपयोग करें। "इनमें से कोई भी काम नहीं करेगा" मेरे लिए खबर है क्योंकि मेरे पास बहुत से ऐप्स हैं। इसके अलावा, मैंने कभी नहीं कहा * रद्दीकरण * सेट करें। असल में मैंने विशेष रूप से कहा कि कतार ऑपरेशन रद्द कर देती है और ऑपरेशन समय-समय पर इस स्थिति की जांच करता है और सत्य होने पर काम करना बंद कर देता है। –

+0

क्या होता है: कतार ऑप्स को रद्द करता है -> ओपी पोस्ट केवीओ नोट को रद्द कर दिया जाता है, स्वयं को रोकता है -> पर्यवेक्षक (आपके कुछ नियंत्रक) नोट्स बदलते हैं, और यदि काम करने के लिए काम है, तो यह मुख्य थ्रेड पर करता है। हर समय काम करता है। सिर्फ इसलिए कि आपका नियंत्रक किसी अन्य थ्रेड पर मैसेज किया गया है इसका मतलब यह नहीं है कि यह इसे संभाल नहीं सकता है। अगर इसे मुख्य धागे पर कुछ करना है, तो आगे बढ़ें और मुख्य धागे पर खुद को कुछ भेजें। –

0

आप कैसे जानते हैं कि आप किस ऑपरेशन को रद्द करना चाहते हैं? जब आप उस बिंदु पर पहुंच जाते हैं जिसे आप रद्द करना चाहते हैं, तो बस [myQueue ऑपरेशंस] पर कॉल करें और संचालन के माध्यम से जाएं जब तक कि आप उन लोगों को न ढूंढें जिन्हें आप रद्द करना चाहते हैं। मुझे लगता है कि यदि आपके पास लाखों ऑपरेशन (या हजारों) हैं तो यह काम नहीं कर सकता है।

[myQueue ऑपरेशंस] थ्रेड सुरक्षित है - कतार सामग्री का एक स्नैपशॉट। आप इसके माध्यम से बहुत तेज़ी से रद्द करने के माध्यम से गोता लगा सकते हैं।

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

4

नहीं, वर्तमान में निष्पादन संचालन को खोजने का कोई तरीका नहीं है। अपनी समस्या को हल करने के लिए

दो तरीके:

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

  2. क्या "भारी उठाने" विधि कुछ मूल्य लौटाती है जो कॉल श्रृंखला को पारित करती है। अपने लक्ष्य को पूरा करने के लिए आपको [currentOperation cancel] पर कॉल करने के लिए भारी उठाने की विधि की आवश्यकता नहीं है। वास्तव में, यह बेहतर होगा कि यह कुछ मूल्य लौटाएगा कि ऑपरेशन "काम पूरा हो गया है, अभी रोकें" का अर्थ समझ जाएगा क्योंकि यह उस वापसी मूल्य की जांच कर सकता है और -isCancelled को थोड़ी देर में कॉल करने के बजाय तत्काल बाहर निकल सकता है बाहर रद्द कर दिया गया है या नहीं।

1

आप वर्तमान ऑपरेशन को थ्रेड शब्दकोश में स्टोर कर सकते हैं। बाहर निकलने से पहले इसे छुटकारा पाने के लिए बस याद रखें। यदि आपने ऑब्जेक्ट बनाया है तो आप सुरक्षित रूप से थ्रेड dict का उपयोग कर सकते हैं।

4

तेज में एक विस्तार है जो चल रहा आपरेशन

extension NSOperationQueue { 
    public var runningOperations: [NSOperation] { 
     return operations.filter {$0.executing && !$0.finished && !$0.cancelled} 
    } 
} 

फिर आप ले सकते हैं पहले एक

if let operation = aQueue.runningOperations.first {} 
+0

स्नीकी, लेकिन मैंने इसे आज़मा दिया और यह स्विफ्ट घोषणा से कक्षाओं सहित [सी [[NSOperationQueue currentQueue] runningOperations] objectAtIndex: 0] का उपयोग करके स्विफ्ट घोषणा से कक्षाओं समेत काफी सुंदर ढंग से काम करता है। – eGanges

1

आप [NSOperationQueue currentQueue] & का एक संयोजन [उपयोग कर सकते हैं देता है के साथ आया एनएसटीएचड वर्तमान थ्रेड] इसे पूरा करने के लिए।

अनिवार्य रूप से, आपको वर्तमान क्यूई पर संचालन के माध्यम से लूप की आवश्यकता है और वर्तमान थ्रेड पर चल रहे ऑपरेशन को ढूंढना होगा।

एनएसओपरेशन उस धागे तक पहुंच प्रदान नहीं करता है, जिस पर यह चल रहा है, इसलिए आपको उस संपत्ति को स्वयं जोड़ना होगा और इसे असाइन करना होगा।

आप शायद पहले से ही NSOperation उपवर्गीकरण और एक मुख्य उपलब्ध कराने, ताकि उपवर्ग के लिए एक 'धागा' संपत्ति जोड़ने कर रहे हैं: यह है कि संपत्ति के लिए

@interface MyOperation : NSOperation 
    @property(nonatomic,strong) NSThread *thread ; 
@end 

फिर, अपने 'मुख्य' आवंटित वर्तमान सूत्र में

myOperation.thread = [NSThread currentThread] 

फिर आप एक 'currentOperation' विधि जोड़ सकते हैं:

+(MyOperation *)currentOperation 
{ 
    NSOperationQueue *opQueue = [NSOperationQueue currentQueue] ; 
    NSThread *currentThread = [NSThread currentThread] ; 

    for(MyOperation *op in opQueue.operations) { 
     if([op isExecuting] && [op respondsToSelector:@selector(thread)]) { 
       if(op.thread == currentThread) { 
        return (op) ; 
       } 
      } 
     } 
    } 

    return nil ; 
}