我有一个回调函数,可能来自任何线程。当我收到这个回调时,我想在主线程上执行某个特定任务。
我需要检查是否已经在主线程上,还是在调用下面的代码之前没有进行此检查会有任何惩罚吗?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
我有一个回调函数,可能来自任何线程。当我收到这个回调时,我想在主线程上执行某个特定任务。
我需要检查是否已经在主线程上,还是在调用下面的代码之前没有进行此检查会有任何惩罚吗?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
async
调度回主队列,则它将被运行,但这可能会破坏您的操作的预期时间。例如,在viewDidLoad()
中的UI代码直到显示视图后才运行。 - pkamb对于您上述描述的异步调度情况,您不需要检查是否在主线程上运行。如Bavarious所示,该操作将被排队在主线程上运行。
但是,如果您尝试使用dispatch_sync()
执行上述操作,而且您的回调函数位于主线程上,则应用程序将在那一点上发生死锁。我在我的答案中描述了这一点,因为当我将一些代码从-performSelectorOnMainThread:
移动时,这种行为让我很惊讶。正如我在那里提到的,我创建了一个辅助函数:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
如果你所在的方法不在主线程上,则该代码将在主线程上同步运行一个代码块,并且如果在主线程上,则直接执行该代码块。您可以使用以下语法来使用此功能:
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
dispatch_set_specific()
是否有帮助:https://dev59.com/J2cs5IYBdhLWcg3wfEHa#12806754。 - Brad Larson-isMainThread
将返回YES,并且该块将按照应有的方式内联运行。它保证了在主线程上执行,从而防止最直接的死锁情况(如上所述,并非所有情况,但是我在我的代码中遇到的情况)。 - Brad Larson就像其他答案提到的那样,从主线程中使用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