检查当前线程是否为主线程

有没有办法检查当前线程是否是 Objective-C 中的主线程?

我想做这样的事。

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

看看 NSThread API 文档

有些方法比如

- (BOOL)isMainThread

+ (BOOL)isMainThread

+ (NSThread *)mainThread

更新: 看起来不是正确的解决方案,根据刚才提到的@demosten 的 queue e.h 头

The first thought was brought to me, when I was needed this functionality was the line:

dispatch_get_main_queue() == dispatch_get_current_queue();

And had looked to the accepted solution:

[NSThread isMainThread];

矿井溶液的速度提高了2.5倍。

另外,是的,我检查过了,它适用于所有的线程

下面的模式将确保一个方法在主线程上执行:

- (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
}

如果希望在主线程上执行方法,可以:

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


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

如果想知道是否在主线程上,只需使用调试器即可。在您感兴趣的行上设置一个断点,当程序到达该行时,调用:

(lldb) thread info

这将显示关于您所在线程的信息:

(lldb)线程信息 线程 # 1: tid = 0xe8ad0,0x0000001083515a0 MyApp‘ MyApp。ViewController.sliderMoved (sender = 0x00007fd221486340,self = 0x00007fd22161c1a0)(Objective C.UISlider)-> () + 112 at ViewController.swift: 20,queue = ‘ com.apple.main-thread’,stop reason = breakpoint 2.1

If the value for queue is com.apple.main-thread, then you're on the main thread.

两种方式。从@rano 的回答来看,

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

还有,

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

For Monotouch / Xamarin iOS you can perform the check in this way:

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

快速版


if (NSThread.isMainThread()) {
print("Main Thread")
}

在 Swift3

if Thread.isMainThread {
print("Main Thread")
}

Let isOnMainQueue = 调度 _ queue _ get _ label (调度 _ get _ main _ queue ()) = = DisPATCH _ CURRENT _ QUEUE _ LABEL)

https://stackoverflow.com/a/34685535/1530581检查这个答案

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


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


block();


} else {


[[NSOperationQueue mainQueue] addOperationWithBlock:^{


block();


}];


}


}

note that i check the operation queue, not the thread, as this is a more safer approach

细节

  • Swift 5.1 Xcode 11.3.1

解决方案1。检测任何队列

获取当前的 DispatchQueue? ?

解决方案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
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") }
}