我有一个回调,它可能来自任何线程。当我得到这个回调时,我想在主线程上执行某个任务。
我需要检查我是否已经在主线程上-或者在调用下面的代码之前不执行这个检查有任何惩罚吗?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
我有一个回调,它可能来自任何线程。当我得到这个回调时,我想在主线程上执行某个任务。
我需要检查我是否已经在主线程上-或者在调用下面的代码之前不执行这个检查有任何惩罚吗?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
不,您不需要检查您是否已经在主线程上。通过将块调度到主队列,您只是将块调度到主线程上串行执行,这在相应的运行循环运行时发生。
如果你已经在主线程上,行为是相同的:块被调度,并在主线程的运行循环运行时执行。
对于上面描述的异步分派情况,您不需要检查是否在主线程上。正如Bavarious所指出的,这将简单地排队在主线程上运行。
但是,如果您尝试使用dispatch_sync()来执行上述操作,并且您的回调是在主线程上,那么您的应用程序将在此时死锁。我在这里的回答中描述了这一点,因为当从-performSelectorOnMainThread:移动一些代码时,这种行为让我感到惊讶。正如我在那里提到的,我创建了一个helper函数:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
如果你所在的方法当前不在主线程上,它会在主线程上同步运行一个块,如果在主线程上,它会内联执行块。你可以使用如下语法来使用这个:
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
正如其他答案所提到的,来自主线程的dispatch_async很好。
然而,根据您的用例,有一个副作用,您可能会认为它是一个缺点:由于块调度在队列上,它将不会执行,直到控制返回到运行循环,这将有延迟块执行的效果。
例如,
NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");
将打印出来:
before dispatch async
after dispatch async
inside dispatch async block main thread from main thread
出于这个原因,如果你希望块在外层NSLog之间执行,dispatch_async将无法帮助你。
不,你不需要检查你是否在主线程中。以下是如何在Swift中做到这一点:
runThisInMainThread { () -> Void in
runThisInMainThread { () -> Void in
// No problem
}
}
func runThisInMainThread(block: dispatch_block_t) {
dispatch_async(dispatch_get_main_queue(), block)
}
它包括在我的回购作为一个标准函数,检查它:https://github.com/goktugyil/EZSwiftExtensions