问题描述
|
我有一个可能来自任何线程的回调。当我收到此回调时,我想在主线程上执行某些任务。
我需要检查我是否已经在主线程上吗?或者通过调用下面的代码不执行此检查是否有任何损失?
dispatch_async(dispatch_get_main_queue(),^{
// do work here
});
解决方法
不,您不需要检查您是否已经在主线程上。通过将块分配到主队列,您只需调度要在主线程上串行执行的块,这将在运行相应的运行循环时发生。
如果您已经在主线程上,则行为是相同的:该块已调度,并在运行主线程的运行循环时执行。
,对于上面描述的异步调度情况,您不需要检查自己是否在主线程上。正如Bavarious所指出的,这将简单地排队等待在主线程上运行。
但是,如果尝试使用ѭ1进行上述操作,并且回调位于主线程上,则此时应用程序将死锁。我在这里的答案中对此进行了描述,因为当从
-performSelectorOnMainThread:
中移出某些代码时,这种行为使我感到惊讶。正如我在此处提到的,我创建了一个辅助函数:
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