Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 两个异步调用的同步_Ios_Objective C_Multithreading_Asynchronous - Fatal编程技术网

Ios 两个异步调用的同步

Ios 两个异步调用的同步,ios,objective-c,multithreading,asynchronous,Ios,Objective C,Multithreading,Asynchronous,早上好 当我的应用程序启动时,我有两个异步调用: 一个获取推送通知的设备令牌,另一个尝试将用户登录到Facebook 如果没有两个异步调用的结果,我就不能继续应用程序进程 目前,我正在做这样的事情:两个布尔值didFBConnect和didDeviceTokenObtained 我正在运行一个线程(显然很糟糕): 你知道处理这种情况的正确方法是什么吗 BR您应该在登录和令牌调用完成时调用相同的函数,并检查一次条件,不要在while循环中执行此操作: - (void)faceBookSuccess

早上好

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

如果没有两个异步调用的结果,我就不能继续应用程序进程

目前,我正在做这样的事情:两个布尔值
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之前,您可以切换到主线程。是的,这比我的