同步两个异步调用

时间:2014-06-16 09:10:13

标签: ios objective-c multithreading asynchronous

早上好,

我的应用程序启动时有两个异步调用: 一个获取推送通知的设备令牌,另一个尝试将用户登录到Facebook。

如果我没有两个异步调用的结果,我不能继续申请过程。

目前,我正在做这样的事情:两个布尔didFBConnectdidDeviceTokenObtained

我在这个线程中运行(显然非常糟糕):

while(!(didFBConnect && didDeviceTokenObtained)){ 
}
myFunctionToContinue();

你知道处理这种情况的正确方法是什么吗?

BR

3 个答案:

答案 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:

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Multithreading/ThreadSafety/ThreadSafety.html

https://developer.apple.com/library/ios/documentation/cocoa/reference/NSCondition_class/Reference/Reference.html

而不是设置两个布尔变量,你应该signal两个条件,并且它们都有主线程/延续线程wait(无论以哪种顺序)。

我建议不要使用普通变量进行同步,因为如果不对CPU和编译器进行假设,则无法保证变量按照预期的顺序分配。如果你这样做,你会很幸运,它将无法运作,否则你将花费大量时间调试竞争条件,你将得到它。