2012-03-15 40 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); 

阻擋塊執行後所有先前提交的塊已經完成執行,和阻擋塊之後提交的任何塊將被強制等待,直到阻擋塊已完成。同樣,由於原因很明顯,您不能在全局隊列中使用障礙塊。您必須創建您自己的併發隊列。

相關問題