2011-12-21 12 views
14

मेरे पास एक NSRunLoop ऑब्जेक्ट है, जिसमें मैं टाइमर और स्ट्रीम संलग्न करता हूं। यह बहुत अच्छा काम करता है। इसे रोकना एक और कहानी है।CFRunLoopRun() बनाम [NSRunLoop रन]

मैं [runLoop run] का उपयोग कर लूप चलाता हूं।

यदि मैं CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]) का उपयोग करके लूप को रोकने का प्रयास करता हूं, तो लूप रुक जाएगा नहीं। अगर मैं इसके बजाय CRunLoopRun() का उपयोग कर लूप शुरू करता हूं, तो यह काम करता है। मैंने यह भी सुनिश्चित किया है कि कॉल सही धागे पर बनाया गया है (जो मेरा कस्टम रन लूप चला रहा है)। मैंने pthread_self() के साथ इसे डीबग किया है।

मुझे एक मेलिंग सूची संग्रह मिला, जहां एक डेवलपर ने कहा "CRunLoopStop() का उपयोग करके परेशान न करें अगर आपने NSRunLoop की रन विधि का उपयोग करके लूप शुरू किया है"। मैं समझ सकता हूं कि यह तरीका क्यों है - आप आम तौर पर कार्यों के एक ही सेट से प्रारंभकर्ताओं और फाइनलरों को जोड़ते हैं।

"सीएफ का सहारा लेने" के बिना आप NSRunLoop को कैसे रोकते हैं? मुझे विधि NSRunLoop पर नहीं दिखाई दे रही है। डॉक्स का कहना है कि आप तीन तरीकों से एक रन पाश बंद कर सकते हैं:

  1. कॉन्फ़िगर एक टाइमआउट मान के साथ चलाने के लिए
  2. बताएँ रन पाश CFRunLoopStop()
  3. का उपयोग करके सभी इनपुट सूत्रों निकालें को रोकने के लिए रन पाश, लेकिन यह एक अविश्वसनीय रन पाश को रोकने के लिए है क्योंकि आप कभी पता नहीं क्या कर सकते हैं के पीछे अपनी पीठ

खैर रन लूप में क्या अटक रास्ता है, मैं पहले से ही 2 की कोशिश की और वहाँ यह करने के लिए लग रहा है एक "बदसूरत", क्योंकि आप सीएफ में खोदना है 3. सवाल से बाहर है - मैं गैर निर्धारक कोड कल्पना नहीं करता हूं।

यह हमें 1 के साथ छोड़ देता है। यदि मैं दस्तावेज़ों को सही ढंग से समझता हूं, तो आप पहले से मौजूद रन लूप में "टाइम" नहीं जोड़ सकते हैं। आप केवल टाइमआउट के साथ नए रन लूप चला सकते हैं। यदि मैं एक नया रन लूप चलाता हूं, तो यह मेरी समस्या का समाधान नहीं करेगा, क्योंकि यह केवल एक नेस्टेड रन लूप बनाएगा। मैं अभी भी पुराने में वापस आऊंगा, वैसे ही मैं रुकना चाहता था ... सही? मैंने शायद इसे गलत समझा होगा। साथ ही, मैं लूप को टाइमआउट मान के साथ नहीं चलाना चाहता हूं। यदि मैं करता हूं, तो मुझे सीपीयू चक्र (कम टाइमआउट मान) और प्रतिक्रियाशीलता (उच्च टाइमआउट मान) जलने के बीच एक व्यापार करना होगा।

यह अभी सेटअप मेरे पास है (छद्म कोड-ish):

Communicator.h

@interface Communicator : NSObject { 
    NSThread* commThread; 
} 

-(void) start; 
-(void) stop; 
@end 

Communicator.m

@interface Communicator (private) 
-(void) threadLoop:(id) argument; 
-(void) stopThread; 
@end 

@implementation Communicator 
-(void) start { 
    thread = [[NSThread alloc] initWithTarget:self 
            selector:@selector(threadLoop:) 
             object:nil]; 
    [thread start]; 
} 

-(void) stop { 
    [self performSelector:@selector(stopThread) 
       onThread:thread 
       withObject:self 
      waitUntilDone:NO]; 
    // Code ommitted for waiting for the thread to exit... 
    [thread release]; 
    thread = nil; 
} 
@end 

@implementation Communicator (private) 
-(void) stopThread { 
    CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]); 
} 

-(void) threadLoop:(id) argument { 
    // Code ommitted for setting up auto release pool 

    NSRunLoop* runLoop = [NSRunLoop currentRunLoop]; 

    // Code omitted for adding input sources to the run loop 

    CFRunLoopRun(); 
    // [runLoop run]; <- not stoppable with 

    // Code omitted for draining auto release pools 

    // Code omitted for signalling that the thread has exited 
} 
@endif 

मैं क्या कर रहा हूँ करने के लिए? क्या यह सीएफ के साथ गड़बड़ करने के लिए आम/अच्छा पैटर्न है? मैं फाउंडेशन को काफी अच्छी तरह से नहीं जानता। सीएफ परत में हस्तक्षेप संभवतः खतरनाक है (स्मृति भ्रष्टाचार, असंगतता, स्मृति रिसाव के संबंध में)? क्या मैं हासिल करने की कोशिश कर रहा हूं, हासिल करने के लिए एक बेहतर पैटर्न है?

उत्तर

7

आप अच्छी तरह से कर रहे हैं। जब आप फाउंडेशन के साथ अपना लक्ष्य प्राप्त नहीं कर सकते हैं तो कोरफाउंडेशन का उपयोग करने में कोई समस्या नहीं है। CoreFoundation सी है, यह ऊपर गड़बड़ करने के लिए आसान स्मृति प्रबंधन के साथ है, लेकिन वहाँ NSRunLoop बजाय CFRunLoop का प्रयोग करने में कोई आंतरिक खतरा है (sometimes it may even be safer: जबकि NSRunLoop नहीं है CFRunLoop एपीआई धागा सुरक्षित हैं)।

यदि आप अपने NSRunLoop को रोकना चाहते हैं, तो आप इसे runMode:beforeDate: का उपयोग करके चला सकते हैं। runMode:beforeDate: जैसे ही इनपुट स्रोत संसाधित हो जाता है, इसलिए आपको टाइमआउट तिथि तक पहुंचने तक प्रतीक्षा करने की आवश्यकता नहीं होती है।

NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
NSDate *date = [NSDate distantFuture]; 
while (!runLoopIsStopped && [runLoop runMode:NSDefaultRunLoopMode beforeDate:date]); 

फिर, रन पाश को रोकने के लिए, आप बस YES को runLoopIsStopped सेट करना होगा।

+0

आह, चालाक! मैंने नहीं देखा कि 'runMode' केवल एक बार भाग गया। क्या रन लूप को बार-बार शुरू करके कोई महत्वपूर्ण प्रदर्शन जुर्माना लगाया गया है? –

+0

नहीं, ऐसा नहीं है: इस प्रकार '- [NSRunLoop रन] 'और' - [NSRunLoop runUntilDate:]' कार्य है। –

+1

थ्रेड नहीं रुक जाएगा यदि आप अभी सेट करें loopIs को YES पर रोक दिया गया है। आपको इसे YES पर सेट करने और उस रनलोप के धागे पर एक क्रिया करने की आवश्यकता है, अन्यथा [runLoop runMode: NSDefaultRunLoopMode पहले दिनांक: दिनांक] बाहर नहीं निकलता है। यह मुझे समझने के लिए उम्र ले गया। – Pada

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