2011-10-21 11 views
9

कैसे मुझे यकीन है कि मेरी समारोह केवल मुख्य थ्रेड पर चलाया जाता है सुनिश्चित कर सकते हैं समारोह मुख्य थ्रेड पर चलाता करें?
इस तरह एक समारोह माना जाता है 'बुरे' (यह UI तत्व अद्यतन करता है)?केवल

-(void)updateSomethingOnMainThread { 
if (![[NSThread currentThread] isEqual:[NSThread mainThread]]) 
    [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO]; 
else { 
    // Do stuff on main thread 
} 
} 

मैं इसे इस तरह लिखा था एक दूसरे समारोह होने से बचाने के लिए, शुरू मैं इसे इस तरह था:

-(void)updateSomethingOnMainThread_real { 
    // Do stuff on main thread 
} 

-(void)updateSomethingOnMainThread { 
    [self performSelectorOnMainThread:@selector(updateSomethingOnMainThread_real) withObject:nil waitUntilDone:NO]; 
} 
+2

संभावित डुप्लिकेट [क्या गोलाकार विधि कॉलिंग की अनुमति है?] (Http://stackoverflow.com/questions/7706329/is-circular-method-calling-allowed) – ughoavgfhw

उत्तर

8

यह ठीक है। आप मुख्य धागे पर कोड निष्पादित करने के लिए जीसीडी का भी उपयोग कर सकते हैं।

चेकआउट इस अतः पोस्ट।

GCD to perform task in main thread

3

वैकल्पिक रूप से, आप Grand Central Dispatch API उपयोग कर सकते हैं, लेकिन यह बहुत आसान नहीं है: जो बहुत सरल है

-(void)updateSomethingOnMainThread { 
    void (^doStuff)(void) = ^{ 
     // stuff to be done 
    }; 

    // this check avoids possible deadlock resulting from 
    // calling dispatch_sync() on the same queue as current one 
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 
    if (mainQueue == dispatch_get_current_queue()) { 
     // execute code in place 
     doStuff(); 
    } else { 
     // dispatch doStuff() to main queue 
     dispatch_sync(mainQueue, doStuff); 
    } 
} 

अन्यथा, तुल्यकालिक कॉल की जरूरत नहीं है, तो आप dispatch_async() कॉल कर सकते हैं:

-(void)updateSomethingOnMainThread { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     // do stuff 
    }); 
} 
+1

उस कोड से सावधान रहें, अगर आप उस फ़ंक्शन को कॉल करते हैं मुख्य धागा यह बांध जाएगा। – NJones

+0

ओह, ठीक है, खेद है। इसलिए मैं अगर वर्तमान कतार मुख्य कतार है विधि की जाँच करनी चाहिए और यदि नहीं, तो यह प्रेषण और यदि हां, तो ठीक है, जगह में ब्लॉक निष्पादित लगता है? यही कारण है कि गैर GCD समाधान :) – ayoy

+0

लोगन के जवाब के आधार पर की तुलना में अधिक जटिल कोड होगा, मुझे लगता है कि आप पहले से ही सही है। कोई चेक की आवश्यकता नहीं है। – thelaws

5

मैंने यह सरल # परिभाषा लिखा है जिसे मैं बड़ी सफलता के साथ उपयोग कर रहा हूं:

#define ensureInMainThread(); if (!NSThread.isMainThread) { [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO]; return; } 

उस स्थिति में आपके विधि, यह मानते हुए यह parameterless है, मुख्य थ्रेड पर निष्पादन की गारंटी के लिए ayoy की विधि के आधार पर GCD कार्यान्वयन को यह

- (void) updateTheThings { 
     ensureInMainThread(); 
     [self.dog setTailWag:YES]; 
     // etc... 
+0

आप मापदंडों कैसे निपटेंगे? – Moshe

+2

@Moshe क्या पैरामीटर?मुझे लगता है कि विधि को किसी पैरामीटर की आवश्यकता नहीं है। :) – Kjuly

+0

क्या होगा अगर मैं एक पैरामीटर के साथ एक पैरामीटर के साथ एक विधि को पास करना चाहता था? – Moshe

15

एक विकल्प के रूप की तरह लग रहा है, मैं GCD आधारित निम्न का उपयोग मेरी कोड में समारोह (another answer of mine से तैयार):

void runOnMainThreadWithoutDeadlocking(void (^block)(void)) 
{ 
    if ([NSThread isMainThread]) 
    { 
     block(); 
    } 
    else 
    { 
     dispatch_sync(dispatch_get_main_queue(), block); 
    } 
} 

फिर आप इस सहायक समारोह कहीं भी अपने कोड में उपयोग कर सकते हैं:

runOnMainThreadWithoutDeadlocking(^{ 
    // Do stuff that needs to be on the main thread 
}); 

यह गारंटी देता है कि संलग्न ब्लॉक में किए गए कार्यों को हमेशा मुख्य धागे पर चलाया जाएगा, इससे कोई फर्क नहीं पड़ता कि कौन सा धागा इसे कॉल करता है। यह थोड़ा कोड जोड़ता है और यह स्पष्ट रूप से स्पष्ट है कि मुख्य थ्रेड पर कौन से कोड को चलाने की आवश्यकता है।

+0

+1 ब्रैड, क्या आप संक्षेप में "बिना डेडलॉकिंग" नाम की व्याख्या कर सकते हैं? जोखिम क्या है, और कौन सी तकनीक इससे बचेंगी? 'WaitUntilDone' के साथ 'प्रदर्शन' चयनकर्ता नहीं है 'NO' डेडलॉकिंग भी नहीं है? –

+2

@Yar - मैं उत्तर में लिंक के उत्तर में यह समझाता हूं: http://stackoverflow.com/a/5226271/19679। मुख्य कतार में एक सिंक्रोनस प्रेषण का उपयोग करना ('-performSelectorOnMainThread:' 'waitUntilDone' के साथ सेट 'के समान) डेडलॉक होगा अगर इसे मुख्य थ्रेड पर पहले से चलने वाले कुछ में कहा जाता है। यह मुझे आश्चर्यचकित कर दिया, और मुझे उपरोक्त सहायक समारोह बनाने के लिए प्रेरित किया। '-performSelectorOnMainThread: 'इस समस्या में कोई समस्या नहीं है, भले ही' waitUntilDone' को YES पर सेट किया गया हो। मुख्य कतार में असीमित प्रेषण में समान डेडलॉकिंग समस्या नहीं होती है। –