早上好,
我的应用程序启动时有两个异步调用: 一个获取推送通知的设备令牌,另一个尝试将用户登录到Facebook。
如果我没有两个异步调用的结果,我不能继续申请过程。
目前,我正在做这样的事情:两个布尔didFBConnect
和didDeviceTokenObtained
。
我在这个线程中运行(显然非常糟糕):
while(!(didFBConnect && didDeviceTokenObtained)){
}
myFunctionToContinue();
你知道处理这种情况的正确方法是什么吗?
BR
答案 0 :(得分:5)
可能的解决方案是创建GCD调度组。看下面的这个例子(简单的应用程序),在同一个方法中,你将异步调用不在主线程中,你将: 1.获得全局队列 2.创建一个调度组 3.在全局队列和组中分派两个作业的异步(FB连接和推送通知令牌) 4.添加一个调度组,等待组中的作业完成 5.等待之后添加你的myFunctionToContinue()
所以你要做的就是将两个工作排队,然后将它们分组,然后等待完成。这比在等待两个作业完成时让线程处于循环中更有效。
" gcdGroup"在主线程中没有调用,但在专用串行队列中是为了避免在组等待时阻塞主线程。
通常,如果您的并发作业是高度异步的并且提供了很大的灵活性,那么使用GCD组非常方便,因为您可以添加其他条件而不会影响代码(只需创建块并放入组中)。此外,您还可以调度创建自己的组的块,从而创建复杂的组图。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
dispatch_queue_t serial_queue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
dispatch_async(serial_queue, ^{
[self gcdGroup];
});
NSLog(@"Main thread not blocked...");
return YES;
}
- (void)gcdGroup {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"Start First job");
sleep(5);
NSLog(@"End First job");
});
dispatch_group_async(group, queue, ^{
NSLog(@"Start second job");
sleep(arc4random()%5);
NSLog(@"End second job");
});
NSLog(@"Now waiting for group to finish...");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"End of group");
}
答案 1 :(得分:1)
你应该在登录和令牌调用完成时调用相同的函数并检查一次条件,不要在while循环中执行此操作:
- (void)faceBookSuccess {
...
didFBConnect = YES;
[self tryToContinue];
}
- (void)tokenSuccess {
...
didDeviceTokenObtained = YES;
[self tryToContinue];
}
- (void)tryToContinue {
if(didFBConnect && didDeviceTokenObtained) {
myFunctionToContinue();
}
}
答案 2 :(得分:0)
看看NSCondition:
和
而不是设置两个布尔变量,你应该signal
两个条件,并且它们都有主线程/延续线程wait
(无论以哪种顺序)。
我建议不要使用普通变量进行同步,因为如果不对CPU和编译器进行假设,则无法保证变量按照预期的顺序分配。如果你这样做,你会很幸运,它将无法运作,否则你将花费大量时间调试竞争条件,你将得到它。