我无法弄清楚为什么以下代码无序调用。它只是为了暴露他们所调用的顺序而不按顺序编写。这很重要,因为我将这些用于互相等待的Web服务调用,但他们并没有。所以,它可能只是我对如何使用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 :(得分: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
答案 1 :(得分: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