如何在运行最终任务之前等待所有异步任务的完成

时间:2015-12-16 23:08:57

标签: objective-c asynchronous health-kit

我必须误解dispatch_group,因为我的dispatch_group_notify调用在单个dispatch_group_async块内的异步调用结束之前正在运行。这是我的代码:

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t dispatchGroup = dispatch_group_create();

    // create operation for each HKTypeIdentifier for which we want to retrieve information
    for( NSString *hkType in typesToRetrieve){
            dispatch_group_async(dispatchGroup, queue, ^{
                     // this method runs several HK queries each with a completion block as indicated below
                    [self getDataForHKQuantity: hkType withCompletion:^(NSArray *results) {
                     // this completion blocks runs asynchronously as HK query completion block
                     // I want to runCompletionBlock only after
                     // all these processResultsArray calls have finished
                    [self processResultsArray:results];
                }];
            });
    }

    dispatch_group_notify(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self runCompletionCheck];
    });

方法getDataForHKQuantity依次使用完成块向HealthKit运行异步查询。在运行HealthKit查询的所有这些完成块之后,我需要运行runCompletionCheck,但现在发生的事情是runCompletionCheck在查询中的代码之前运行。完成块已运行。对我来说,这意味着dispatch_group_notify以及dispatch_group_async不能按我需要的方式工作,那么我做错了什么或者处理这个问题的最佳方法是什么?

总体目标:向HealthKit发出一堆并发查询,运行完成块,然后运行所有这些完成块时,运行最终方法。

这个问题有两个问题。 首先,健康工具包查询并不总是运行完成块。我开始使用计数器系统,在健康工具包查询中有一个计数器。完成块。这就是告诉我这些完成块不会一直运行的原因。 其次,我不知道我尝试运行多少查询,因为它取决于用户拥有的数据源。

那么,问题是,在运行最终方法之前,如何运行一系列运行状况工具包查询中的所有完成块?

1 个答案:

答案 0 :(得分:3)

您的-getDataForHKQuantity:withCompletion:方法是异步的。因此,通过您的调度组,您正在将调用同步到这些方法,而不是在方法本身中完成的工作。

换句话说,您正在嵌套两个异步调用,但只通过调度组同步第一个级别。

您需要提出一个不同的策略来控制您的程序流程。

两个例子:

1。使用信号量(阻塞)

前段时间,我使用信号量进行类似的任务,不确定这是最好的策略,但在你的情况下它会像:

semaphore = dispatch_semaphore_create(0);

for( NSString *hkType in typesToRetrieve)
{
    [self getDataForHKQuantity: hkType withCompletion:^(NSArray *results) {

        // register running method here

        [self processResultsArray:results];

        if (isLastMethod) // need to keep track of concurrent methods running
        {
            dispatch_semaphore_signal(semaphore);
        }
    }];
}

// your program will wait here until all calls to getDataForHKQuantity complete
// so you could run the whole thing in a background thread and wait for it to finish
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

2。使用dispatch_group

dispatch_group_t serviceGroup = dispatch_group_create();

for( NSString *hkType in typesToRetrieve)
{
    dispatch_group_enter(serviceGroup);

    [self getDataForHKQuantity: hkType withCompletion:^(NSArray *results) {

        [self processResultsArray:results];
        dispatch_group_leave(serviceGroup);
    }];
}

dispatch_group_notify(serviceGroup,dispatch_get_main_queue(),^{
    // Won't get here until everything has finished
});

另请查看this link以获取更多信息。