2009-07-18 9 views
8

मुझे लगता था कि मैं एक बुद्धिमान बुद्धिमान व्यक्ति था।
सेब की "थ्रेडिंग प्रोग्रामिंग गाइड" ने मेरी अहंकार को आत्मविश्वास बनाए रखा है।उद्देश्य-सी रन लूप रोकने और विधि को फिर से शुरू करने के लिए?

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

कोड धागा शुरू होता है।
अगर बूलियन मान stuffToDo सच है,
तो यह doStuff कॉल:
अन्यथा
यह थोड़ा आराम है।
तब तक यह दोबारा लूप करता है जब तक कि मैं इसे

मेरा वर्तमान कोड अपर्याप्त लगता है, क्योंकि यह 'सामान टोडो' की जांच करता रहता है जब भी ऐसा करने के लिए कुछ भी नहीं होता है।

मैं सामान से छुटकारा पा सकता हूं और केवल आवश्यकतानुसार थ्रेड को रद्द कर सकता हूं।
यह भी अपर्याप्त लगता है, और इसका मतलब है कि मुझे सावधान रहना होगा कि मेरे पास पहले से चलने पर एक नया धागा गलती से न हो।

मुझे यकीन है कि इस सवाल का जवाब कुशलता से मेरी स्थिति को सुलझाने एप्पल के "प्रोग्रामिंग गाइड सूत्रण" के "रन पाश प्रबंधन" खंड में कहीं पाया जा सकता है के लिए कर रहा हूँ
शायद यह कस्टम इनपुट सूत्रों

शामिल है लेकिन मैं वास्तव में हूँ इस दस्तावेज़ को चुनौतीपूर्ण खोजना।
ऐसा लगता है कि यह दस्तावेज़ मेरे दिमाग में बहुत सारे धागे पैदा कर रहा है और गणना एक रुकावट के लिए पीसती है।

enum eRenderThreadMode 
{ 
    render_not_started, 
    render_run, 
    render_cancel, 
    render_finished 
}; 


- (IBAction) startThread:(id)sender 
{ 
    self.renderThreadMode = render_run; 
    label.text = @"doing stuff"; 
    [NSThread detachNewThreadSelector:@selector(keepDoingStuff) toTarget:self withObject:nil]; 

} 

- (void)keepDoingStuff 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    while (renderThreadMode == render_run) 
    { 
     if(stuffToDo) 
     { 
      [self doStuff]; 
     } 
     else 
     { 
      [NSThread sleepForTimeInterval:kLittleRest]; 
     } 
    } 
    self.renderThreadMode = render_finished; 
    [pool release]; 
} 


- (IBAction)stopThread:(id)sender 
{ 
    self.renderThreadMode = render_stop; 

    while (self.renderThreadMode == render_cancel) 
    { 
     [NSThread sleepForTimeInterval:kLittleRest]; 
    } 
} 

उत्तर

7

आप एक तुल्यकालन उद्देश्य यह है कि अपने माध्यमिक धागे पर सोता है इस्तेमाल कर सकते हैं। This Apple page इंगित करता है कि ऐसी स्थितियां हैं जिन्हें स्थितियां कहा जाता है जो आप चाहते हैं जो कर सकते हैं। किसी शर्त या समान सिंक्रनाइज़ेशन ऑब्जेक्ट का उपयोग करने से आपके धागे को केवल तब तक जागृत किया जाएगा जब काम किया जा सके (या जब थ्रेड के लिए समय हो)।

+0

सहमत हुए। एक एनएससीन्डिशन लॉक का प्रयोग करें। यह एक मानक थ्रेडिंग निर्माण है। –

+0

धन्यवाद, ऐसा लगता है कि यह वही करेगा जो मैं चाहता हूं –

+0

मैंने एनएससीडिशन लॉक की बजाय एम्स सुझाव के रूप में एनएससीओंडिशन का उपयोग किया। क्या आप वास्तव में हालत लॉक के बजाय हालत का मतलब था? यदि हां, तो आप एनएससींडिशन लॉक का उपयोग करके इसे कार्यान्वित करने की कल्पना कैसे करेंगे। मैंने पहले उद्देश्य सी धागे के साथ काम नहीं किया है, और विभिन्न दृष्टिकोणों के बारे में सुनने में दिलचस्पी है। –

7

हाँ, आप सही हैं कि आप एक रनलोप का उपयोग करना चाहते हैं, जो आप खो रहे हैं वह यह सब सेट अप करना है। मैं आपकी पोस्ट को संशोधित करने जा रहा हूं और समझा रहा हूं कि क्या हो रहा है। चिंता मत करो अगर यह आप को धमकाता है, यह मुश्किल है और कुछ gotchas आप ही के बारे में अनुभव से

- (IBAction) startThread:(id)sender 
{ 
    self.renderThreadMode = render_run; 
    label.text = @"doing stuff"; 
    self.backgroundThread = [[NSThread alloc] initWithTarget:self selector:@selector(keepDoingStuff) object:nil]; 
    [self.backgroundThread start];  
} 

//Okay, this is where we start changing stuff 
- (void)keepDoingStuff 
{ 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

     //A runloop with no sources returns immediately from runMode:beforeDate: 
     //That will wake up the loop and chew CPU. Add a dummy source to prevent 
     //it. 

     NSRunLoop *runLopp = [NSRunLoop currentRunLoop]; 

     NSMachPort *dummyPort = [[NSMachPort alloc] init]; 
     [runLoop addPort:dummyPort forMode:NSDefaultRunLoopMode]; 
     [dummyPort release]; 
     [pool release]; 

     while (1) 
     { 
       NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; 
       [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
       [loopPool drain]; 
     } 
} 

ठीक सीख रहे हैं ताकि इस बिंदु पर आप उपरोक्त कोड को देखकर किया जाना चाहिए और सोच "ठीक है, कि देखते हैं, एक अच्छा नींद धागा हो सकता है, लेकिन यह कुछ भी नहीं करता है। और यह सच है, लेकिन चूंकि इसमें एक सक्रिय रनलोप है, हम इसके खिलाफ आधारित रनलोप को कुछ भी कर सकते हैं, इसमें प्रदर्शनकर्ता शामिल करें: ऑन थ्रेड: withObject: waitUntilDone:

- (void) doStuffOnBackgroundThread 
{ 
    [self performSelector:@selector(doStff) onThread:self.backgroundThread withObject:nil waitUntilDone:NO]; 
} 

जब आप उपरोक्त विधि को अपने मुख्य धागे (या किसी अन्य थ्रेड) पर कॉल करते हैं तो यह विभिन्न तर्कों को मार्शल करेगा और निर्दिष्ट के रनलोप को एनक्यू करेगा ied धागा, इसे जरूरी के रूप में जागना। इस मामले में self.background का कारण बन जाएगा runMode से wake करने के लिए थ्रेड: पहले दिनांक :, execute -doStuff, फिर चक्र वापस लूप को उखाड़ फेंकें और सोने में वापस सोने में प्रतीक्षा करें मोड: पहले दिनांक:।यदि आप थ्रेड को फाड़ने में सक्षम होना चाहते हैं तो आप अपने कोड में थोड़ी देर के लूप में एक वैरिएबल सेट कर सकते हैं, हालांकि याद रखें कि जब तक आप इसे जगाते हैं तो थ्रेड सो जाएगा, तो शायद यह संभवतः encapsulate कि एक विधि में जो नियंत्रण चर के माध्यम से नियंत्रण चर सेट करता है: ऑन थ्रेड: withObject: waitUntilDone :, प्लस के रूप में इसका अर्थ यह होगा कि वेरिएबल केवल पृष्ठभूमि थ्रेड से सेट किया जाएगा जो सिंक्रनाइज़ेशन समस्याओं को सरल बनाता है।

ठीक है, तो मुझे लगता है कि आपकी समस्या हल हो जाती है, इसलिए अनिवार्य प्लग बनाने का समय: क्या आप वाकई थ्रेड के साथ ऐसा करना चाहते हैं? NSOperation और NSOperationQueue एक बहुत ही सरल समाधान हो सकता है जो आपके लिए सभी थ्रेडिंग मुद्दों का ख्याल रखता है यदि आपको केवल कुछ डेटा संसाधित करने के लिए कुछ समय लगता है। वे काम को शेड्यूल करेंगे, निर्भरताओं का प्रबंधन करेंगे, और थ्रेड को फायर/फायर करेंगे और साथ ही साथ सभी रनलोप वेक/नींद की चीजों का ख्याल रखेंगे।

+0

महान विस्तृत उत्तर के लिए धन्यवाद। एनएसओपरेशन का उपयोग करके बंद कर दिया गया था, क्योंकि मैं इंप्रेशन के तहत था, एनएसओपरेशन को काम की एक सीमित मात्रा को संसाधित करने के लिए डिज़ाइन किया गया है, जहां मैं थ्रेड को किक करना चाहता हूं और इसे अनिश्चित अवधि के लिए चलाना चाहता हूं, (न्यूनतम 2 सेकंड, अधिकतम तक बैटरी फ्लैट चलती है?) तो मुझे पता है कि मुझे यकीन नहीं है कि मुझे एनएसओपरेशन पर धागे का उपयोग करने की ज़रूरत है, यह केवल अस्पष्ट भावना पर आधारित था, जिसकी जांच –

+0

की जांच करने के लिए सबसे अधिक मूल्यवान थी। आप या तो कर सकते हैं। एक NSOperationQueue खाली होने तक चलते रहेंगे, लेकिन आप इसे किसी भी समय पर रख सकते हैं और इसमें एनएसओपरेशंस फेंक सकते हैं और इसे संभाल सकते हैं। –

+0

धन्यवाद लुई, उपर्युक्त के बारे में कुछ प्रश्न हैं, जहां रन लूप आते हैं? मेरे मामले में जब थ्रेड काम कर रहा है, तो मैं इसे कॉल करना जारी रखना चाहता हूं: जैसे ही मैं अपने हस्तक्षेप के बिना कर सकता हूं, इसलिए मैं संरचना बदल सकता हूं इसलिए मैं कुछ कहता हूं: [स्वयं प्रदर्शन चयनकर्ता: @ चयनकर्ता (doAsMuchStuffAsYouCanUntilItellYouToStop) ऑन थ्रेड: self.background थ्रेड के साथ ऑब्जेक्ट: nil waitUntilDone: NO]; –

संबंधित मुद्दे