1

我不明白爲什麼下面的代碼被亂序調用。它只是爲了公開它們被調用的順序而寫的。這很重要,因爲我正在使用這些Web服務調用,它們應該彼此等待,而他們不是。所以,這可能只是我對如何使用GCD的概念。GCD函數亂序調用

var group: dispatch_group_t = dispatch_group_create() 
var groupTwo: dispatch_group_t = dispatch_group_create() 
var queue: dispatch_queue_t = dispatch_get_main_queue() 

dispatch_group_notify(groupTwo, queue) {() -> Void in 
    print("3rd") // Should be called 3rd 
} 

dispatch_group_enter(group) 
    print("1st") // Should be called 1st 
dispatch_group_leave(group) 

dispatch_group_notify(group, queue) {() -> Void in 
    dispatch_group_enter(groupTwo) 
      print("2nd") // Should be called 2nd 
    dispatch_group_leave(groupTwo) 
} 

這是命令它打印在:

1st 
3rd 
2nd 

爲什麼是順序錯了嗎?不應該3rd只叫一次dispatch_group_leave(groupTwo)叫?爲什麼事先被調用?我認爲這是dispatch_group_notify()被用於。

編輯:對不起,我只是修復了組名。起初忘了編輯一些。

+0

,你做'dispatch_group_enter(groupTwo)塊,如果'groupTwo'爲空,並在第一時間之後執行的第一個'dispatch_group_notify'檢查'版畫「第三「一旦發現它是。 – dan

+0

我沒有想到'dispatch_group_notify'甚至會在dispatch_group_leave之前被調用。有沒有更好的方法來完成我想要做的事情? – chicobermuda

+0

這是不是很清楚你想做什麼。我假設你爲了這個問題抽象了所有的細節,但是很難說出你應該做什麼。 – dan

回答

0
dispatch_group_notify(groupTwo, queue) {() -> Void in 
    print("3rd") // Should be called 3rd 
} 

dispatch_group_notify將在組爲空時將第一個塊提交給隊列。最初,該組是空的。因此,它將異步提交給主隊列。

這裏

dispatch_group_enter(group) 
    print("1st") // Should be called 1st 
dispatch_group_leave(group) 

您有效地打印到控制檯上的主隊列 - 此打印

1st 

這裏

dispatch_group_notify(group, queue) {() -> Void in 
    dispatch_group_enter(groupTwo) 
      print("2nd") // Should be called 2nd 
    dispatch_group_leave(groupTwo) 
} 

你異步提交其被排隊的第二塊在第一塊之後。

現在,第一塊執行,打印

3rd 

最後,第二塊打印:

2nd 
1

這聽起來像你需要等待兩個或多個遠程調用的結果然後才能發出最終的遠程呼叫。比方說,你有這些參數,這將通過遠程調用來填充兩個屬性:

var a:String? = nil // populated asynchronously 
var b:String? = nil // populated asynchronously 

然後,假設你的遠程調用是這樣的:

func getParameterA(completionHandler:(String) -> Void) { 
    print("Getting parameter A") 
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { 
     NSThread.sleepForTimeInterval(0.2) 
     completionHandler("A") 
     print("Got parameter A") 
    } 
} 

func getParameterB(completionHandler:(String) -> Void) { 
    print("Getting parameter B") 
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { 
     NSThread.sleepForTimeInterval(0.1) 
     completionHandler("B") 
     print("Got parameter B") 
    } 
} 

func getResult(a:String, b:String, completionHandler:(String) -> Void) { 
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { 
     NSThread.sleepForTimeInterval(0.05) 
     completionHandler("This is the result of \(a) and \(b)") 
    } 
} 

在現實中,他們將遠程調用而不是睡在後臺線程上。

然後,你的代碼來填充ab看起來就像這樣:

// the blocks in the parameter group are responsible for setting a and b 
let parameterGroup = dispatch_group_create() 
dispatch_group_enter(parameterGroup) 
getParameterA() { parameter in 
    // set the value of a asynchronously 
    self.a = parameter 
    dispatch_group_leave(parameterGroup) 
} 
dispatch_group_enter(parameterGroup) 
getParameterB() { parameter in 
    // set the value of b asynchronously 
    self.b = parameter 
    dispatch_group_leave(parameterGroup) 
} 

最後,你可以用dispatch_group_notify定義最終完成處理程序只執行一次,有沒有更多的任務parameterGroup

let finalGroup = dispatch_group_create() 
dispatch_group_enter(finalGroup) 
dispatch_group_notify(parameterGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { 
    self.getResult(self.a!, b:self.b!) { result in 
     print("-- \(result)") 
     dispatch_group_leave(finalGroup) 
    } 
} 
dispatch_group_wait(finalGroup, DISPATCH_TIME_FOREVER) 

finalGroup不是嚴格必要的,但我需要它來得到範例在XCTest內工作。

輸出將是這樣的:

Getting parameter A 
Getting parameter B 
Got parameter B 
Got parameter A 
-- This is the result of A and B