我正在研究dispatch_async()
的工作原理。
我在main()
中尝试了这个代码段:
typedef void(^VoidBlock)();
VoidBlock aBlock = ^{
NSLog(@"do work in main queue");
};
dispatch_async(dispatch_get_main_queue(), aBlock);
但是Block从未被调用过。我想也许主线程在块运行之前就结束了。 然后我尝试了这个:
dispatch_group_t aGroup = dispatch_group_create();
VoidBlock aBlock = ^{
NSLog(@"do work in main queue");
dispatch_group_leave(aGroup);
};
dispatch_group_enter(aGroup);
dispatch_async(dispatch_get_main_queue(), aBlock);
dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER);
这也不起作用(Block不会被调用)。
区别在于现在主要线程(正确)阻塞了语句dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER)
有什么问题?
答案 0 :(得分:4)
我怀疑您没有创建iOS项目(或任何其他触发runloop的项目类型),而是“命令行工具”。如果是这种情况:
您的第一个方法
一般情况下,您的第一种方法很好,但在触发异步调用之前,main()
会返回(因此您的应用已完成运行)。
您的第二种方法
您在第二种方法中得到了正确的想法:等到您的异步作业完成。
您的实现虽然导致死锁。 wait
阻止从它(主线程)调用它的线程,直到你的块完成运行,但是当主线程被阻塞时块永远不会运行。
<强>解决方案强>
要解决此问题,请在与等待队列不同的队列上发送:
dispatch_group_t aGroup = dispatch_group_create();
VoidBlock aBlock = ^{
NSLog(@"do work in main queue");
dispatch_group_leave(aGroup);
};
dispatch_group_enter(aGroup);
// dispatch on another queue than the one wait will block
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), aBlock);
dispatch_group_wait(aGroup, DISPATCH_TIME_FOREVER);
这样主队列就等待(阻塞),而你的块可以在另一个队列上执行。
@Ishahaks answer创建“单一视图应用程序”而不是“命令行工具”也可以工作(因为问题原来被称为“iOS”),即使在main()
中也是如此。因此,iOS应用程序触发了一个runloop(while(true) { // wait for events }
),因此应用程序在从main()
返回后仍然运行。请参阅Apples Runloop Documentation。
答案 1 :(得分:0)
如果您正在为iOS开发,请使用&#34; New&#34; &#34;项目&#34; &#34;单一视图应用程序&#34;,然后将您的代码放入application:didFinishLaunchingWithOptions
,如下所示:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
typedef void(^VoidBlock)();
VoidBlock aBlock = ^{
NSLog(@"do work in main queue");
};
dispatch_async(dispatch_get_main_queue(), aBlock);
return YES;
}