在串行执行其他异步任务之后执行异步任务

Perform async task, after serial execution of other async tasks

我有一个包含主文件和附加文件的内容。

问题来了:首先我需要下载、解压并将附加文件插入数据库,然后才对主文件执行相同的操作。附加文件需要串行下载,主文件必须在它们之后下载。

正确的做法是什么?

现在我是这样做的:

- (void)checkIfPlacesAreDownloaded:(NSArray *)places{

    [SVProgressHUD showWithStatus:@"Downloading places"];

    dispatch_group_t group = dispatch_group_create();

    for(NSDictionary *place in places){

            BOOL result = [IDGDatabaseManager checkIfPlaceIsDownloaded:place];

            if(!result){
                dispatch_group_enter(group);
                [self downloadPlace:place withCompletionHandler:^{
                    [IDGDatabaseManager setPlaceDownloaded:[place objectForKey:@"place_ID"]
                                       WithCompletionBlock:^(BOOL success, NSError *error) {
                                           dispatch_group_leave(group);
                                       }];
                }];

            }
    }

    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        [self downloadExcursionWithParams:self.excursionDownloadResponse];
    });


}

只有在 "places" 数组中只有一个文件时才有效。如果有多个文件,他们开始并行下载,这不适合我。

我认为 downloadPlace:withCompletionHandler: 方法在后台并发队列上异步工作。这就是文件并行下载 运行 的原因。我会改用私有串行队列或简单地执行下一步:

[SVProgressHUD showWithStatus:@"Downloading places"];

dispatch_group_t group = dispatch_group_create();

// create a serial background queue to run the file downloads
dispatch_queue_attr_t qosAttribute = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
dispatch_queue_t myQueue = dispatch_queue_create("com.YourApp.YourQueue", qosAttribute);

for(NSDictionary *place in places){

    BOOL result = [IDGDatabaseManager checkIfPlaceIsDownloaded:place];

    if(!result){
        dispatch_group_enter(group);

        // run the download async on the serial bg queue
        __weak __typeof(self) weakSelf = self;
        dispatch_async(myQueue, ^{
            __typeof(self) strongSelf = self;

            // we need a semaphore to wait for the download completion
            dispatch_semaphore_t sema = dispatch_semaphore_create(0);
            [strongSelf downloadPlace:place withCompletionHandler:^{
                [IDGDatabaseManager setPlaceDownloaded:[place objectForKey:@"place_ID"]
                                   WithCompletionBlock:^(BOOL success, NSError *error) {
                                       dispatch_semaphore_signal(sema);
                                   }];
            }];
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            dispatch_group_leave(group);
        });
    }
}

dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    [self downloadExcursionWithParams:self.excursionDownloadResponse];
});