dispatch_group_wait永远等待
dispatch_group_wait waits forever
我正在研究 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)
语句上
有什么问题?
如果您正在为 iOS 开发,则使用 "New" "Project" "Single View Application",然后像这样将您的代码放入 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;
}
我怀疑您没有创建 iOS 项目(或任何其他触发运行循环的项目类型),而是 "Command Line Tool"。如果是这样的话:
你的第一个方法
一般来说,您的第一种方法没问题,但是 main()
returns(因此您的应用会在触发异步调用之前完成 运行)。
你的第二种方法
您在第二种方法中的想法是正确的:等待异步作业完成。
不过您的实施导致了死锁。 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);
这样主队列正在等待(阻塞),而您的块可以(正在)在另一个队列上执行。
to create a "Single View Application" instead of a "Command Line Tool" would also work (as the question was originally taged as "iOS"), even in main()
. The reason therefore is that iOS applications trigger a runloop (while(true) { // wait for events }
), so the application still runs after returning from main()
. See Apples Runloop Documentation.
我正在研究 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)
有什么问题?
如果您正在为 iOS 开发,则使用 "New" "Project" "Single View Application",然后像这样将您的代码放入 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;
}
我怀疑您没有创建 iOS 项目(或任何其他触发运行循环的项目类型),而是 "Command Line Tool"。如果是这样的话:
你的第一个方法
一般来说,您的第一种方法没问题,但是 main()
returns(因此您的应用会在触发异步调用之前完成 运行)。
你的第二种方法
您在第二种方法中的想法是正确的:等待异步作业完成。
不过您的实施导致了死锁。 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);
这样主队列正在等待(阻塞),而您的块可以(正在)在另一个队列上执行。
main()
. The reason therefore is that iOS applications trigger a runloop (while(true) { // wait for events }
), so the application still runs after returning from main()
. See Apples Runloop Documentation.