Ios 两个异步调用的同步
早上好 当我的应用程序启动时,我有两个异步调用: 一个获取推送通知的设备令牌,另一个尝试将用户登录到Facebook 如果没有两个异步调用的结果,我就不能继续应用程序进程 目前,我正在做这样的事情:两个布尔值Ios 两个异步调用的同步,ios,objective-c,multithreading,asynchronous,Ios,Objective C,Multithreading,Asynchronous,早上好 当我的应用程序启动时,我有两个异步调用: 一个获取推送通知的设备令牌,另一个尝试将用户登录到Facebook 如果没有两个异步调用的结果,我就不能继续应用程序进程 目前,我正在做这样的事情:两个布尔值didFBConnect和didDeviceTokenObtained 我正在运行一个线程(显然很糟糕): 你知道处理这种情况的正确方法是什么吗 BR您应该在登录和令牌调用完成时调用相同的函数,并检查一次条件,不要在while循环中执行此操作: - (void)faceBookSuccess
didFBConnect
和didDeviceTokenObtained
我正在运行一个线程(显然很糟糕):
你知道处理这种情况的正确方法是什么吗
BR您应该在登录和令牌调用完成时调用相同的函数,并检查一次条件,不要在while循环中执行此操作:
- (void)faceBookSuccess {
...
didFBConnect = YES;
[self tryToContinue];
}
- (void)tokenSuccess {
...
didDeviceTokenObtained = YES;
[self tryToContinue];
}
- (void)tryToContinue {
if(didFBConnect && didDeviceTokenObtained) {
myFunctionToContinue();
}
}
您应该在登录和令牌调用完成时调用相同的函数,并检查一次条件,不要在while循环中执行此操作:
- (void)faceBookSuccess {
...
didFBConnect = YES;
[self tryToContinue];
}
- (void)tokenSuccess {
...
didDeviceTokenObtained = YES;
[self tryToContinue];
}
- (void)tryToContinue {
if(didFBConnect && didDeviceTokenObtained) {
myFunctionToContinue();
}
}
看看NSCondition: 及 您不应该设置两个布尔变量,而应该设置两个条件,并让主线程/连续线程对这两个条件进行等待(无论顺序如何)
我建议不要使用普通变量进行同步,因为如果不对CPU和编译器进行假设,就不能保证变量按预期顺序分配。如果你这么做了,也许你会很幸运,它不会起作用,否则你会花很多时间调试比赛条件,你会得到它。看看比赛条件: 及 您不应该设置两个布尔变量,而应该设置两个条件,并让主线程/连续线程对这两个条件进行等待(无论顺序如何)
我建议不要使用普通变量进行同步,因为如果不对CPU和编译器进行假设,就不能保证变量按预期顺序分配。如果你这么做了,也许你会很幸运,它不会起作用,否则你将花费大量时间调试比赛条件,这是你应得的。一个可能的解决方案是创建一个GCD调度组。查看下面的示例(简单应用程序),在相同的方法上,您将不在主线程中进行异步调用,您将: 1.获取全局队列 2.创建调度组 3.在全局队列和组中异步调度两个作业(FB connect和Push通知令牌) 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");
}
一个可能的解决方案是创建一个GCD调度组。查看下面的示例(简单应用程序),在相同的方法上,您将不在主线程中进行异步调用,您将: 1.获取全局队列 2.创建调度组 3.在全局队列和组中异步调度两个作业(FB connect和Push通知令牌) 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");
}
坏消息,APNS注册失败回调并不总是被调用。是的,这是我积压工作中的另一个问题:pBad新闻,APNS注册失败回调不总是被调用。是的,这是我积压工作中的另一个问题:pHow聪明而简单。。。谢谢你的意见!使用这种方法需要注意的唯一一点是,
myFunctionToContiue
可能不会在主线程上被调用,这将导致您在更新任何UI元素时出现问题-我建议dispatch\u async(dispatch\u get\u main\u queue(),^{myFunctionToContinue();})
还有一个风险,就是myFunctionToContinue
将被调用两次@viggio24的解决方案是安全的,如果两次回调不在主线程上,它可能被调用两次。在校准tryToContinu
te之前,您可以切换到主线程。这是多么聪明和简单啊。。。谢谢你的意见!使用这种方法需要注意的唯一一点是,myFunctionToContiue
可能不会在主线程上被调用,这将导致您在更新任何UI元素时出现问题-我建议dispatch\u async(dispatch\u get\u main\u queue(),^{myFunctionToContinue();})
还有一个风险,就是myFunctionToContinue
将被调用两次@viggio24的解决方案是安全的,如果两次回调不在主线程上,它可能被调用两次。在校准tryToContinu
te之前,您可以切换到主线程。是的,这比我的