10

我正在尝试编写一些线程安全的方法,所以我正在使用:

...
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_sync(main,^{
  [self doSomethingInTheForeground];
});
...

但是如果我在不必要的主线程上,我可以跳过所有那些调度调用,所以我想知道我目前在哪个线程上。我怎么知道这个?

或者,也许这样做并没有什么不同(在性能上)?

做这个比较好吗?

if (dispatch_get_main_queue() == dispatch_get_current_queue()){...}
4

9 回答 9

13

更新答案

Apple 文档已更改,现在说“当从提交块的上下文之外调用时,如果从主线程执行调用,则此函数返回主队列。如果从任何其他线程进行调用,则此函数返回默认并发队列。” 所以检查dispatch_get_main_queue() == dispatch_get_current_queue()应该有效。

原始答案

使用dispatch_get_main_queue() == dispatch_get_current_queue()将不起作用。文档dispatch_get_current_queue说“当在提交块的上下文之外调用时,此函数返回默认并发队列”。默认并发队列不是主队列。

[NSThread isMainThread]应该为你想要的工作。请注意,这[NSThread isMainThread]对于除主队列以外的队列可能是正确的,例如,当dispatch_sync从主线程调用时。

于 2011-02-11T01:25:20.127 回答
12

随着 的折旧dispatch_get_current_queue(),相当于(dispatch_get_main_queue() == dispatch_get_current_queue())

现在是通过队列标签比较,即:

(dispatch_queue_get_label(dispatch_get_main_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))
于 2016-01-08T20:35:44.830 回答
4

更新的答案:

dispatch_get_current_queue() 现在已弃用。

原答案:

在 OS-X 10.8 上,在头文件 (queue.h) 中,在 dispatch_get_current_queue() 函数上方的注释中,它是这样写的:

当在主线程上调用 dispatch_get_current_queue() 时,它可能会或可能不会返回与 dispatch_get_main_queue() 相同的值。比较两者并不是测试代码是否在主线程上执行的有效方法。

我发现因为一个

assert(dispatch_get_current_queue() == dispatch_get_main_queue());

在我的代码中,在 iOS 上运行良好但在 OS-X 上失败。

于 2012-11-23T20:04:31.690 回答
3

iOS 的新功能:10.0+ 和 macOS:10.12+(tvOS:10.0+,watchOS:3.0+)。

斯威夫特 4+:

检查是否在主队列上运行:

if (RunLoop.current == RunLoop.main) {
    print("On main queue")
}
   

断言是否在主队列上运行:

dispatchPrecondition(condition: .onQueue(.main))
// Code running on main queue
 

如果不在主队列上运行,则断言:

dispatchPrecondition(condition: .notOnQueue(.main))
// Code NOT running on main queue

ObjC:检查是否在主队列上运行:

if ([[NSRunLoop currentRunLoop] isEqual: [NSRunLoop mainRunLoop]]) {
    NSLog(@"Running on main");
} else {
    NSLog(@"Not running on main");
}
   

断言是否在主队列上运行:

dispatch_assert_queue(dispatch_get_main_queue());
   

如果不在主队列上运行,则断言:

dispatch_assert_queue_not(dispatch_get_main_queue());

注意:mainThread != mainQueue 主队列总是在主线程上运行,但一个队列可能在主线程上运行而不是主队列。所以,不要混合线程和队列测试!

于 2019-01-31T16:30:14.343 回答
2

如果您在 Objective-C 中并且希望在主线程上同步发生某些事情,那么使用起来会不会更简单

[self performSelectorOnMainThread: @selector(doSomethingInTheForeground) 
                       withObject: nil 
                    waitUntilDone: YES];

这样做的好处是,如果您已经在主线程上,没关系,消息以正常方式发送。

于 2011-02-09T09:06:55.700 回答
1

dispatch_get_current_queue()除非您不进行调试,否则使用它是不安全的。正如手册页中明确写的那样dispatch_queue

注意事项

代码不能对dispatch_get_current_queue(). 返回的队列可能有任意的策略,这些策略可能会让试图调度队列工作的代码感到惊讶。策略列表包括但不限于队列宽度(即串行与并发)、调度优先级、安全凭证或文件系统配置。因此,dispatch_get_current_queue()必须仅用于身份测试或调试。

更好的事情(可能更复杂)是同步后台线程:

dispatch_sync(backgroundqueue,^{
  [self doSomethingInTheBackground];
});

也许我完全错了,但这就是我的建议。

于 2011-02-09T08:57:54.100 回答
0

其实用起来是没问题的。

文件说

当从提交块的上下文之外调用时,如果调用是从主线程执行的,则此函数返回主队列。如果调用来自任何其他线程,则此函数返回默认并发队列。

于 2011-10-24T21:11:07.563 回答
0

请注意,主队列与主线程不同。当在主线程的队列上使用 dispatch_sync() 时,非主队列很容易在主线程上运行。更罕见的是,在使用 dispatch_main() 代替 NSRunLoops 的命令行工具中(即,除了 Cocoa/iOS 应用程序),主队列可能在主线程之外的其他东西中执行。

如果您正在处理需要主队列而不仅仅是主线程的代码(例如,期望从 queue_get_specific 在主队列上设置的值的代码,据传闻 VectorKit/MapKit 会这样做),最好检查显式主队列而不是主线程。

一种显式检查主队列的选项:

BOOL MyIsMainQueue(void)
{
    static char MAIN_IND_KEY;
    static char MAIN_IND_VAL;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        dispatch_queue_set_specific(dispatch_get_main_queue(), &MAIN_IND_KEY, &MAIN_IND_VAL, NULL);
    });

    return dispatch_get_specific(&MAIN_IND_KEY) == &MAIN_IND_VAL;
}

使用 DISPATCH_CURRENT_QUEUE_LABEL 的答案也应该有效,并且可能更好,尽管在 MacOS 10.9 和 iOS7 之前定义 DISPATCH_CURRENT_QUEUE_LABEL 时可能不起作用(即崩溃)。

于 2018-05-26T18:24:14.527 回答
-1

dispatch_get_current_queue自 iOS 6.0 起已弃用。看起来[NSThread isMainThread]是唯一的出路。

于 2013-08-27T19:08:55.530 回答