1

Я не могу понять, почему следующий код вызывается из строя. Это сделано только для того, чтобы разоблачить заказ, в котором они вызваны. Это важно, потому что я использую их с вызовами веб-службы, которые должны ждать друг друга, а это не так. Таким образом, это может быть просто моя концепция использования 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().

EDIT: Извините, я только что установил имена групп. Сначала можно было отредактировать.

+0

блока, где вы 'dispatch_group_enter (groupTwo)' выполняется после того, как в первый раз ваш первый 'dispatch_group_notify' проверяет,' groupTwo' пуст и печатает «третьего «как только он обнаружит, что это так. – 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)") 
    } 
} 

На самом деле, они сделают удаленное вместо того, чтобы спать на фоне потоков.

Затем код для заполнения a и b будет выглядеть следующим образом:

// 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 
Смежные вопросы