0

我需要在调用 api(NS​​URLSessionDataTask 异步)的单独线程中一个接一个地运行 3 个方法。我查看了调度组,但这似乎同时运行方法 1 和 2,然后在它们完成时运行方法 3:

dispatch_group_t group = dispatch_group_create();

//METHOD 1
dispatch_group_enter(group);
[self method1WithCompletion:^(BOOL success){
    dispatch_group_leave(group);
}];

//METHOD 2
dispatch_group_enter(group);
[self method2WithCompletion:^(BOOL success){
    dispatch_group_leave(group);
}];

dispatch_group_notify(group,dispatch_get_main_queue(),^{
    //METHOD 3
});

我需要它来运行方法 1,何时完成运行方法 2,何时完成最终运行方法 3(对方法进行排队)。

我知道我可以在每个完成时链接方法以运行下一个,但我认为会有更好的方法来解决这个问题......有什么想法吗?

4

2 回答 2

0

你很亲密。

dispatch_group_enter并且公司只处理使它成为的位,以便在调用传递到的块之前完成所有dispatch_group_enter进入 s 的操作。dispatch_group_tdispatch_group_notify

所以我们可以在等待任务时好好利用它们。我们可以为每个需要完成的异步任务使用一个组,而不是只有一个组等待每个任务完成:

// You can get a global queue or create your own, it doesn't really matter
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// Create a group for each task you want to wait for
dispatch_group_t group1 = dispatch_group_create();
dispatch_group_t group2 = dispatch_group_create();

// Call your first task on the first group
dispatch_group_enter(group1);
[self method1WithCompletion:^(BOOL success){
    // Task is completed, so signal that it has finished
    dispatch_group_leave(group1);
}];

// Call your 2nd task on the 2nd group
dispatch_group_enter(group2);
// Make the second task wait until group1 has completed before running
dispatch_group_notify(group1, queue, ^{
    // METHOD 2
    [self method2WithCompletion:^(BOOL success){
        // Signal to the group that the task has completed
        dispatch_group_leave(group2);
    }];
});

// Nothing is waiting on the 3rd task, so no need to create a group for it
dispatch_group_notify(group2,dispatch_get_main_queue(),^{
    //METHOD 3
    // Do whatever you need to do in here
});

以下是有关调度队列以及如何使用它们的更多信息。

编辑:对不起,我完全改变了我的答案。一旦你留下你的评论,我就觉得你调用的任务是异步的,使用串行dispatch_queue_t不会有什么不同!(这些块是串行运行的,但是method2会在method1之后立即运行,而不是等待完成)

于 2015-02-10T11:51:25.053 回答
0

已编辑: 我不再这么认为了,cjwirth在下面的评论中驳斥了我的假设

我认为仍然可以使用串行队列的方法(但这只是假设,我没有检查它)。主要思想是将组的任务分派到串行队列中,dispatch_group_enter(group)在分派之前使用并dispatch_group_leave(group)在您的方法1..2完成时使用。让我展示它应该是什么:

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_group_t group = dispatch_group_create();

//METHOD 1
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
   [self method1WithCompletion:^(BOOL success){
   dispatch_async(queue, ^{                     
                     dispatch_group_leave(group);
             });
    }];
});

//METHOD 2
dispatch_group_enter(group);
dispatch_group_async(group, queue, ^{
   [self method2WithCompletion:^(BOOL success){
   dispatch_async(queue, ^{                     
                     dispatch_group_leave(group);
             });
    }];
});

dispatch_group_notify(group,dispatch_get_main_queue(),^{
    //METHOD 3
});

注意:这种实现看起来有问题。因为我们已经有了 NSOperationQueue,所以我建议你将你NSURLSessionDataTask的东西包装到 NSOperation 中并按顺序执行它们

于 2015-02-10T17:17:22.353 回答