我有几个线程,一旦完成工作,我需要在每个操作中调用一次myMergeBlock
方法。我无法使用dispatch_once
,因为我希望以后能够拨打myMergeBlock
。
某些伪代码看起来像这样,但还不是线程安全的:
BOOL worker1Finished, worker2Finished, worker3Finished;
void (^mergeBlock)(void) = ^{
if (worker1Finished && worker2Finished && worker3Finished)
dispatch_async(queue, myMergeBlock); // Must dispatch this only once
}
void (^worker1)(void) = ^{
...
worker1Finished = YES;
mergeBlock();
}
void (^worker2)(void) = ^{
...
worker2Finished = YES;
mergeBlock();
}
void (^worker3)(void) = ^{
...
worker3Finished = YES;
mergeBlock();
}
另外,根据调用worker的方式,我不直接调用它们,而是将它们作为参数传递给函数。
答案 0 :(得分:3)
您想使用调度组。首先,创建一个组,安排组中的三个工作人员,然后向该组添加通知块。 看起来应该是这样的:
//create dispatch group
dispatch_group_t myWorkGroup = dispatch_group_create();
//get one of the global concurrent queues
dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL);
//submit your work blocks
dispatch_group_async(myWorkGroup, myQueue, worker1);
dispatch_group_async(myWorkGroup, myQueue, worker2);
dispatch_group_async(myWorkGroup, myQueue, worker3);
//set the mergeBlock to be submitted when all the blocks in the group are completed
dispatch_group_notify(myWorkGroup, myQueue, mergeBlock);
//release the group as you no longer need it
dispatch_release(myWorkGroup);
如果您愿意,可以暂停群组并稍后重复使用。务必在通知之前安排工作。如果您首先尝试安排通知,则会立即发送通知。
我没有测试过这段代码,但我在项目中使用了dispatch_groups。
答案 1 :(得分:1)
这听起来很乱,水平很低。您是否查看了Operation Queues中讨论的Concurrency Programming Guide和调度组和信号量。我认为他们可能会为您的问题提供更简单的解决方案。
答案 2 :(得分:0)
如果您的目标是Lion或iOS 5及更高版本,只要在非全局并发队列上调度块,就可以使用barrier blocks。例如:
dispatch_queue_t customConcurrentQueue = dispatch_queue_create("customQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(customConcurrentQueue, worker1);
dispatch_async(customConcurrentQueue, worker2);
dispatch_async(customConcurrentQueue, worker3);
dispatch_barrier_async(customConcurrentQueue, mergeBlock);
//Some time later, after you're sure all of the blocks have executed.
dispatch_queue_release(customConcurrentQueue);
在所有先前提交的块完成执行之后执行屏障块,并且在屏障块之后提交的任何块将被强制等待直到屏障块完成。同样,由于显而易见的原因,您不能在全局队列上使用障碍块。您必须创建自己的并发队列。