2012-03-15 59 views
0

我有几个线程,一旦它们全部完成工作,我需要每次操作调用一次myMergeBlock方法。我不能使用dispatch_once,因为我希望能够在以后拨打myMergeBlockiOS确保函数仅在每个会话中调用一次

一些伪代码看起来是这样,但还没有线程安全:

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(); 
} 

此外,根据工人的调用方式,我不直接给他们打电话,而是将它们传递到一个功能参数。

+0

为什么没有上述工作?对我来说似乎没问题。 – CodaFi 2012-03-16 00:13:35

回答

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

这听起来非常混乱和低级别。你看过Operation Queues和调度组和信号量,如Concurrency Programming Guide中所讨论的。我认为他们可能会为您的问题提供更简单的解决方案。

+0

确实如drekka所说,如果您使用大型中央调度组功能,则可以在组中的所有任务完成时执行某些操作。 – Pochi 2012-03-16 00:52:37

+0

我已阅读这些文档。我正在考虑实际使用条件互斥。我不确定操作队列是否会有帮助,因为我正在调用诸如'[Object doSomethingWithBlock:^ {}]'这样的工作程序,它将异步执行块中的传入。 – Dex 2012-03-16 01:59:41

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); 

阻挡块执行后所有先前提交的块已经完成执行,和阻挡块之后提交的任何块将被强制等待,直到阻挡块已完成。同样,由于原因很明显,您不能在全局队列中使用障碍块。您必须创建您自己的并发队列。

相关问题