简体   繁体   English

两个CloudKit可以互相调用死锁吗? 怎么修?

[英]Can two CloudKit call deadlock each other? How to fix?

Inside a performQuery an other performQuery is being called. performQuery内部,正在调用另一个performQuery The recordType arguments are same for both, but the predicate s are different. 两者的recordType参数相同,但predicate不同。

The second performQuery never returns, the App just runs and waits for CloudKit to respond. 第二个performQuery永不返回,该应用程序仅运行并等待CloudKit响应。

The pseudo code is like this: 伪代码是这样的:

publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records, error in

    if error == nil {

        //.. problem is not name collision or reusing the same parameter, coming codepart is called though other methods

        publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records, error in

            //THIS LINE WILL NEVER GET REACHED

            if error == nil {

            } else {
                println(error.localizedDescription)
            }
            dispatch_semaphore_signal(sema2)
        })
        dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER)

        //..

    } else {
        println(error.localizedDescription)
    }
    dispatch_semaphore_signal(sema)
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)

It looks like a semaphore threading issue. 看起来是信号量线程问题。 You are reusing the sama parameter. 您正在重用sama参数。 The last dispatch_semaphore_signal must be moved to above inside the else. 最后的dispatch_semaphore_signal必须移到else内部的上方。 Then the first dispatch_semaphore_wait can be removed completely. 然后,可以完全删除第一个dispatch_semaphore_wait。 So it will be like this: 因此它将是这样的:

publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records, error in

    if error == nil {

        //.. problem is not name collision, it is nested though other blocks

        publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records, error in

            //THIS LINE WILL NEVER GET REACHED

            if error == nil {

            } else {
                println(error.localizedDescription)
            }
            dispatch_semaphore_signal(sema)
        })

        //..

    } else {
        println(error.localizedDescription)
        dispatch_semaphore_signal(sema)
    }
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)

Deadlock was fixed like this: Inner query moved after outer query. 死锁是这样修复的:内部查询在外部查询之后移动。 Both semaphore retained. 两种信号量均保留。 Outer completion handler is finished before inner completion handler would start. 外部完成处理程序将在内部完成处理程序启动之前完成。 From CloudKit returned records are stored in local variables. 从CloudKit返回的记录存储在局部变量中。

var records: [AnyObject]! = []
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records2, error in

    if error == nil {
        records = records2
    } else {
        println(error.localizedDescription)
    }
    dispatch_semaphore_signal(sema)
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)

//HERE I can use records

var records3: [AnyObject]! = []
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records4, error in

    if error == nil {
        records3 = records4
    } else {
        println(error.localizedDescription)
    }
    dispatch_semaphore_signal(sema2)
})
dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER)

//HERE I can use records3 too

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM