在Objective C中尝试使用块。 我遇到了一个奇怪的问题。
下面我创建了一个块并在全局调度队列上提交了异步执行块。 它不会为我打印任何东西。当我用同步替换关键字async时,它可以正常工作并立即打印结果。
@implementation BlockTest
+(void) blocksTest{
__block int m = 0;
void (^__block myblock)(void);
myblock = ^(){
NSLog(@"myblock %u ", ++m);
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"dispatch_async dispatch_get_global_queue");
myblock();
});
}
@end
int main(int argc, const char * argv[])
{
[BlockTest blocksTest];
}
有人可以帮我解决这个问题吗?
答案 0 :(得分:1)
你的程序在块有机会运行之前就已退出。
像dispatch_async()
这样的异步调用的本质是它返回并允许调用者继续,可能在提交的任务完成之前。可能在它开始之前。
因此,+blocksTest
返回main()
中的呼叫网站。 main()
继续结束(顺便说一下,没有返回值,这对非void
函数是不好的)。当main()
返回时,整个过程退出。 GCD正在管理的任何队列,任务,工作线程等都在进程终止期间被拆除。
进程不会等待所有线程退出或空闲。
您可以在dispatch_main()
调用+blocksTest
后致电main()
来解决此问题。但是,在这种情况下,除非您提交一个在某个时刻调用exit()
的任务,否则该程序将永远不会终止。例如,您可以将调用退出在+blocksTest
中创建的块中。
实际上,在这种情况下,因为任务将在后台线程而不是主线程上运行,所以任何延迟立即退出的事情都是足够的。例如,调用sleep()
一秒钟即可。您还可以运行主运行循环一段时间。没有一段时间保证足以使全局队列有机会完成任务,但实际上,它只需要几分之一秒。
如果没有安排输入源或定时器,那么运行循环退出的方法会有复杂性。所以,你必须安排一个虚假的来源(比如NSPort
)。正如你所知道的,如果你没有使用run循环来实现真正的东西,这是一种愚蠢的方法。
答案 1 :(得分:0)
因为当您使用dispatch_async时,该块可能已经开始执行,但尚未到达您打印的位置。但是,如果使用dispatch_sync,则确保在返回之前完成整个块执行。请记住,dispatch_sync是主线程。