Ios 等待异步块完成

Ios 等待异步块完成,ios,grand-central-dispatch,Ios,Grand Central Dispatch,例如,我有一个包含三个异步块的方法。每个块结果都需要执行下一个块以获得最终结果。所以,我要找的是一个很好的GCD策略,让他们在严格的顺序下运行,没有死锁 __block id task1Result; __block id task2Result; __block id finalResult; [self startTask1:^(id result) { task1Result = result }] [self startTask2:task1Result bl

例如,我有一个包含三个异步块的方法。每个块结果都需要执行下一个块以获得最终结果。所以,我要找的是一个很好的GCD策略,让他们在严格的顺序下运行,没有死锁

__block id task1Result;    
__block id task2Result;    
__block id finalResult;  

[self startTask1:^(id result) { task1Result = result }]  

[self startTask2:task1Result block:^(id result) { task2Result = result }]  

[self startTask3:task2Result block:^(id result) { finalResult = result }]  
UPD。我找到了一个解决方案:

dispatch_semaphore_t sem = dispatch_semaphore_create(0);

__block id task1Result;    
__block id task2Result;    
__block id finalResult;  

[self startTask1:^(id result) { 
  task1Result = result;
  dispatch_semaphore_signal(sem);
}];  
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

[self startTask2:task1Result block:^(id result) { 
  task2Result = result;
  dispatch_semaphore_signal(sem);
}];  
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

[self startTask3:task2Result block:^(id result) { finalResult = result }];

但在我的例子中,我遇到了一些库方法的问题,导致应用程序死锁。> 创建如下所述的串行调度队列:

简言之:

dispatch_queue_t queue;
queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
    printf("Do some work here.\n");
});
dispatch_async(queue, ^{
    printf("When finished do next task.\n");
});

请注意,您必须自己处理队列。

如果每个任务直接使用上一个任务的结果,您不能从其前一个任务的完成回调启动每个任务吗?不过,您仍然需要一个调度组来等待最后一个任务完成

dispatch_group_t group = dispatch_group_create();
__block id result;

dispatch_group_enter(group);
[self startTask1:^(id task1Result) {
  [self startTask2:task1Result block:^(id task2Result) {
    [self startTask3:task2Result block:^(id finalResult) {
      result = finalResult;
      dispatch_group_leave(group);
    }];
  }];
}];

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

您可能遇到的一个复杂问题是,尝试将完成处理程序中的任务排入队列是否会产生死锁风险,即如果您的完成处理程序是在处理排入队列的任务的同一个串行队列上调用的。

调度队列很好,但如果他在调度异步队列中调用异步API,这不会让他更接近等待所有API调用的目标。@Claus Jørgensen:队列是串行的,一次只负责执行一个任务。你能解释一下为什么这还不够吗?如果你把
dispatch\u async(另一个队列,^{})
放在
dispatch\u async
里面,它就不会等它完成了。假设他的任务API不是基于GCD构建的,那么您的建议不会产生任何影响。这取决于OP是否在调用现有的API。感谢您的澄清,我没有想到非GCDstuff@ClausJ我不认为我们需要考虑其他API,因为这个问题与调度有关。dogsgod说得对,正确的解决方案是使用串行队列。不要使用信号量。这是最糟糕的解决方案,因为它很容易导致优先级反转。请使用串行队列来序列化您的操作。您能给我一个示例代码,说明在我的案例中应该如何使用它们吗?创建一个串行队列,并将您的块提交给它。他们将按顺序执行。dogsgod在下面给了你一个例子。但据我所知,在他的例子中,dispatch_async不会等待子块完成。。我错了吗?dispatch\u async将立即返回调用方。dispatch_sync将仅在执行块后返回调用方。串行队列确保按顺序而不是并行执行所有块。在执行块之前,您是否关心调用线程阻塞?如果是,请使用dispatch_sync。您是否关心块只按顺序执行?如果是,请使用串行队列。基于这个问题,指出了三个需要按顺序执行的异步操作,即带有串行队列的dispatch\u async。这种方式太难看了。我想摆脱它。你觉得它难看主要是因为完成处理程序的嵌套吗?