我正在尝试编写一些线程安全的方法,所以我正在使用:
...
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_sync(main,^{
[self doSomethingInTheForeground];
});
...
但是如果我在主线程上没有必要,我可以跳过所有这些调度调用,所以我想知道我目前在做什么线程。我怎么知道这个?
或者,也许它在性能方面没有差别?
可以进行这种比较吗?
if (dispatch_get_main_queue() == dispatch_get_current_queue()){...}
答案 0 :(得分:12)
更新回答:
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]
对于除主队列之外的队列可以为true,例如,当从主线程调用dispatch_sync
时。
答案 1 :(得分:11)
折旧为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))
答案 2 :(得分: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上运行失败。
答案 3 :(得分:2)
如果您在Objective-C中并且想要在主线程上同步发生某些事情,那么使用它会不会更简单
[self performSelectorOnMainThread: @selector(doSomethingInTheForeground)
withObject: nil
waitUntilDone: YES];
这样做的好处是,如果你已经在主线程上,那没关系,消息是以正常方式发送的。
答案 4 :(得分:1)
除非您没有调试,否则使用dispatch_get_current_queue()
是不安全的。因为它写得很清楚in the dispatch_queue
man page:
CAVEATS
代码无法对
dispatch_get_current_queue()
返回的队列做出任何假设。返回的队列可能具有任意策略,可能会使尝试调度队列工作的代码感到惊讶。策略列表包括但不限于队列宽度(即串行与并发),调度优先级,安全凭证或文件系统配置。因此,dispatch_get_current_queue()
必须仅用于身份测试或调试。
更好的事情(可能更复杂)是同步后台线程:
dispatch_sync(backgroundqueue,^{
[self doSomethingInTheBackground];
});
也许我完全错了,但这就是我的建议。
答案 5 :(得分:1)
ObjC::检查是否在主队列上运行:
if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {
NSLog(@"Running on main queue");
}
如果在主队列上运行则断言:
dispatch_assert_queue(dispatch_get_main_queue());
确认否是否在主队列上运行:
dispatch_assert_queue_not(dispatch_get_main_queue());
检查是否在主队列上运行(不幸的是没有直接方法):
if (OperationQueue.current?.underlyingQueue?.label == DispatchQueue.main.label) {
print("On main queue")
}
如果在主队列上运行则断言:
dispatchPrecondition(condition: .onQueue(.main))
// Code running on main queue
确认否是否在主队列上运行:
dispatchPrecondition(condition: .notOnQueue(.main))
// Code NOT running on main queue
注意:
mainThread != mainQueue
主队列始终在主队列上运行 线程,但是队列可能正在主线程上运行而没有被 主队列。因此,请勿混合使用线程和队列测试!
答案 6 :(得分:0)
实际上,可以使用。
文档说
当从提交的块的上下文外部调用时,这个 如果从main执行调用,函数将返回主队列 螺纹即可。如果调用是从任何其他线程进行的,则此函数 返回默认的并发队列。
答案 7 :(得分:0)
请注意,主队列与主线程不同。当在主线程的队列上使用dispatch_sync()时,非主队列很容易在主线程上运行。更常见的是,在使用dispatch_main()代替NSRunLoops的命令行工具中(即,除了Cocoa / iOS应用程序之外),主队列可以在主线程之外的其他内容中执行。< / p>
如果你正在处理需要主队列而不仅仅是主线程的代码(比如说代码需要在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时,可能无法正常工作(即崩溃)。
答案 8 :(得分:-1)
dispatch_get_current_queue
已被弃用。看起来[NSThread isMainThread]
是唯一可行的方式。