जांचें कि वर्तमान धागा मुख्य धागा है या नहीं


121

क्या यह जांचने का कोई तरीका है कि वर्तमान धागा ऑब्जेक्टिव-सी में मुख्य धागा है या नहीं?

मैं ऐसा कुछ करना चाहता हूं।

  - (void)someMethod
  {
    if (IS_THIS_MAIN_THREAD?) {
      NSLog(@"ok. this is main thread.");
    } else {
      NSLog(@"don't call this method from other thread!");
    }
  }

अन्य थ्रेड्स से एक विधि को कॉल करने में क्या गलत है?
डेविड David वोंग

जवाबों:



24

यदि आप मुख्य थ्रेड पर एक विधि निष्पादित करना चाहते हैं, तो आप कर सकते हैं:

- (void)someMethod
{
    dispatch_block_t block = ^{
        // Code for the method goes here
    };

    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_async(dispatch_get_main_queue(), block);
    }
}

5
पुराने प्रश्नों के उत्तर स्पष्टीकरण से लाभ उठा सकते हैं कि नया उत्तर मौजूदा उत्तरों से कैसे भिन्न होता है।
जेसन एलर

1
यह ओवरकिल है, अगर कुछ काम मुख्य धागे पर किया जाना चाहिए , तो यह जांचने में कोई फायदा नहीं है कि आप मुख्य धागे पर हैं या नहीं। बस करोNSOperationQueue.mainQueue().addOperationWithBlock { //your work here }
एरिक

3
@ मैं सहमत हूं, लेकिन क्या होगा यदि आप मुख्य थ्रेड में पहले से ही विधि का तत्काल निष्पादन चाहते हैं? आपके सुझाव में विधि को हमेशा मुख्य ऑपरेशन कतार के माध्यम से बाद में निष्पादित करने के लिए भेजा जाता है।
बोहेरना

@boherna सही, यह देखने के लिए कुछ है।
एरिक

@boherna लेट कमेंट, लेकिन आप अपनी टिप्पणी में जो बिंदु बनाते हैं वह और अधिक मजबूत होगा यदि आप अपने उदाहरण के dispatch_sync()बजाय उपयोग dispatch_async()करते हैं।
कालेब


13

यदि आप जानना चाहते हैं कि आप मुख्य धागे पर हैं या नहीं, तो आप बस डिबगर का उपयोग कर सकते हैं। उस पंक्ति पर एक ब्रेकपॉइंट सेट करें जिसमें आप रुचि रखते हैं, और जब आपका कार्यक्रम उस तक पहुंचता है, तो इसे कॉल करें:

(lldb) thread info

यह उस धागे के बारे में जानकारी प्रदर्शित करेगा जिस पर आप हैं:

(lldb) thread info thread #1: tid = 0xe8ad0, 0x00000001083515a0 MyApp`MyApp.ViewController.sliderMoved (sender=0x00007fd221486340, self=0x00007fd22161c1a0)(ObjectiveC.UISlider) -> () + 112 at ViewController.swift:20, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1

यदि मान queueहै com.apple.main-thread, तो आप मुख्य धागे पर हैं।


6

निम्न पैटर्न मुख्य थ्रेड पर एक विधि निष्पादित होने का आश्वासन देगा:

- (void)yourMethod {
    // make sure this runs on the main thread 
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:_cmd/*@selector(yourMethod)*/
                               withObject:nil
                            waitUntilDone:YES];
        return;
    }
    // put your code for yourMethod here
}

_cmdस्वचालित रूप से उस विधि का उपयोग करेगा जिसमें आपका स्निपेट in • ʔ • the में चिपकाया गया है
अल्बर्ट

3

दो तरीके। @ रानो के जवाब से,

[[NSThread currentThread] isMainThread] ? NSLog(@"MAIN THREAD") : NSLog(@"NOT MAIN THREAD");

इसके अलावा,

[[NSThread mainThread] isEqual:[NSThread currentThread]] ? NSLog(@"MAIN THREAD") : NSLog(@"NOT MAIN THREAD");

3
void ensureOnMainQueue(void (^block)(void)) {

    if ([[NSOperationQueue currentQueue] isEqual:[NSOperationQueue mainQueue]]) {

        block();

    } else {

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            block();

        }];

    }

}

ध्यान दें कि मैं ऑपरेशन कतार की जांच करता हूं, धागे की नहीं, क्योंकि यह अधिक सुरक्षित दृष्टिकोण है


यह स्वीकृत उत्तर, मुख्य धागा होना चाहिए! = मुख्य कतार
रेलवेपैर

2

Monotouch / Xamarin iOS के लिए आप इस तरह से चेक कर सकते हैं:

if (NSThread.Current.IsMainThread)
{
    DoSomething();
}
else
{
    BeginInvokeOnMainThread(() => DoSomething());
}



0

विवरण

  • स्विफ्ट 5.1, एक्सकोड 11.3.1

समाधान 1. किसी भी कतार का पता लगाएं

वर्तमान डिस्पैच क्यू प्राप्त करें?

समाधान 2. केवल मुख्य कतार का पता लगाएं

import Foundation

extension DispatchQueue {

    private struct QueueReference { weak var queue: DispatchQueue? }

    private static let key: DispatchSpecificKey<QueueReference> = {
        let key = DispatchSpecificKey<QueueReference>()
        let queue = DispatchQueue.main
        queue.setSpecific(key: key, value: QueueReference(queue: queue))
        return key
    }()

    static var isRunningOnMainQueue: Bool { getSpecific(key: key)?.queue == .main }
}

प्रयोग

if DispatchQueue.isRunningOnMainQueue { ... }

नमूना

func test(queue: DispatchQueue) {
    queue.async {
        print("--------------------------------------------------------")
        print("queue label: \(queue.label)")
        print("is running on main queue: \(DispatchQueue.isRunningOnMainQueue)")
    }
}

test(queue: DispatchQueue.main)
sleep(1)
test(queue: DispatchQueue.global(qos: .background))
sleep(1)
test(queue: DispatchQueue.global(qos: .unspecified))

परिणाम (लॉग)

--------------------------------------------------------
queue label: com.apple.root.background-qos
is running on main queue: false
--------------------------------------------------------
queue label: com.apple.root.default-qos
is running on main queue: false
--------------------------------------------------------
queue label: com.apple.main-thread
is running on main queue: true

0
Here is a way to detect what the current queue is
extension DispatchQueue {
    //Label of the current dispatch queue.
    static var currentQueueLabel: String { String(cString: __dispatch_queue_get_label(nil)) }

    /// Whether the current queue is a `NSBackgroundActivityScheduler` task.
    static var isCurrentQueueNSBackgroundActivitySchedulerQueue: Bool { currentQueueLabel.hasPrefix("com.apple.xpc.activity.") }

    /// Whether the current queue is a `Main` task.
    static var isCurrentQueueMainQueue: Bool { currentQueueLabel.hasPrefix("com.apple.main-thread") }
}

-2

अद्यतन: ऐसा लगता है कि सही समाधान नहीं है, जैसा कि @demosten के अनुसार कतार.ह हेडर के अनुसार

पहला विचार मेरे लिए लाया गया था, जब मुझे जरूरत थी कि यह कार्यक्षमता रेखा थी:

dispatch_get_main_queue() == dispatch_get_current_queue();

और स्वीकृत समाधान की ओर देखा था:

[NSThread isMainThread];

मेरा समाधान 2.5 गुना तेज है।

PS और हाँ, मैंने जाँच की, यह सभी थ्रेड्स के लिए काम करता है


3
समझ में आता है - आपका तरीका obj-c रनटाइम मैसेजिंग सिस्टम के ओवरहेड को बायपास करता है। यद्यपि यदि आप इस तकनीक का उपयोग कर रहे हैं, तो मैं कहूंगा कि इसमें खराब कोड की गंध है, शायद समय से पहले अनुकूलन।
ArtOfWarfare

4
dispatch_get_current_queue ()
iOs

33
आप इसे Apple के queue.h हेडर के विवरण में पढ़ सकते हैं जहाँ dispatch_get_current_queue () परिभाषित है: When dispatch_get_current_queue() is called on the main thread, it may or may not return the same value as dispatch_get_main_queue(). Comparing the two is not a valid way to test whether code is executing on the main thread.
demosten
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.