使用 dispatch_async 的方块

Using blocks with dispatch_async

在 Objective C 尝试积木。 我 运行 遇到了一个 st运行ge 问题。

下面我创建了一个块并提交了该块以在全局调度队列上异步执行。 它不会为我打印任何东西。当我用 sync 替换关键字 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];
}

有人可以帮我解决这个问题吗?

您的程序在块有机会 运行 之前退出。

dispatch_async() 这样的异步调用的本质是它 returns 并允许调用者继续,可能在提交的任务完成之前。可能还没有开始。

因此,+blocksTest returns 到 main() 中的调用站点。 main() 一直持续到最后(顺便说一句,没有返回值,这对非 void 函数来说是不好的)。当main()returns时,整个流程退出。 GCD 管理的任何队列、任务、工作线程等都在进程终止期间被拆除。

进程不会等待所有线程退出或空闲。

您可以通过在 main() 中调用 +blocksTest 之后调用 dispatch_main() 来解决这个问题。但是,在那种情况下,程序将永远不会终止,除非您提交一个在某个时候调用 exit() 的任务。例如,您可以将调用 exit 放在您在 +blocksTest.

中创建的块中

实际上,在这种情况下,因为任务将 运行 在后台线程而不是主线程上进行,所以任何延迟立即退出的事情就足够了。例如,调用 sleep() 一秒钟就可以了。您还可以 运行 主 运行 循环一段时间。没有 保证 的时间足以让全局队列有机会 运行 完成您的任务,但实际上,它只需要一小部分一秒钟。

如果没有安排输入源或计时器,运行 运行 循环退出的方法会很复杂。所以,你必须安排一个虚假的来源(比如 NSPort)。如您所知,如果您不使用 运行 循环来处理实际内容,那么这是一种笨拙的方法。

因为你使用dispatch_async的时候,block可能已经开始执行了,但是还没到你打印的地方。但是,如果您使用 dispatch_sync,它会确保整个块的执行在它 returns 之前完成。请记住,dispatch_sync 是主线程。