Ios 在执行另一个块之前执行所有后台线程
我正在尝试在核心数据中加载照片,但这需要一些后台线程,所以碰巧我的对象保存在核心数据中而没有照片,我得到的照片为零。我的团队的照片也是如此 简言之,在每次迭代中,我都会在核心数据中保存一个对象,并且保存速度比加载照片数据快 我试过信号灯、屏障、群组,。。。但都不管用。我确实做错了什么,但我不知道是什么。如果有人能帮助我,我会非常感激,我已经两个星期都在努力解决这个问题了。这是我的代码的简化版本,完整版本可在下面访问:Ios 在执行另一个块之前执行所有后台线程,ios,multithreading,core-data,semaphore,background-thread,Ios,Multithreading,Core Data,Semaphore,Background Thread,我正在尝试在核心数据中加载照片,但这需要一些后台线程,所以碰巧我的对象保存在核心数据中而没有照片,我得到的照片为零。我的团队的照片也是如此 简言之,在每次迭代中,我都会在核心数据中保存一个对象,并且保存速度比加载照片数据快 我试过信号灯、屏障、群组,。。。但都不管用。我确实做错了什么,但我不知道是什么。如果有人能帮助我,我会非常感激,我已经两个星期都在努力解决这个问题了。这是我的代码的简化版本,完整版本可在下面访问: // MARK - ViewDidLoad override func vie
// MARK - ViewDidLoad
override func viewDidLoad() {
// This method is only called once, so you want to create any controls or arrays here
super.viewDidLoad()
// Verifying connectivity to internet
if Reachability.isConnectedToNetwork() == true {
// Getting data from Parse + getDataInBackgroundWithBlock
}else{
}
}
// MARK - Action of the login button
@IBAction func loginBtn_click(sender: AnyObject) {
if usernameTxt.text == "" || passwordTxt.text == "" {
self.displayAlert("Error", message: "Please enter a username and password")
}else{
// MARK - Login the user
PFUser.logInWithUsernameInBackground(usernameTxt.text!, password: passwordTxt.text!) { (user, error) -> Void in
if error == nil {
let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT)
dispatch_async(queue, { () -> Void in
self.getObjectsFromQueryWithAscendingOrder("Add", key: "user", value: userName, ascendingOrder: "added", completionHandler: { (objects1) -> Void in
// Update of an array in background
})
})
dispatch_async(queue, { () -> Void in
// Update of an array in background
})
dispatch_async(queue, { () -> Void in
self.getObjectsFromQueryWithAscendingOrder("Group", key: "membersUsername", value: userName, ascendingOrder: "membersUsername", completionHandler: { (objects3) -> Void in
// Update of an array in background
// MARK - Adding all the users in Core data
for var i = 0; i < usersFromParseDataBase.count; i++ {
let entity = NSEntityDescription.entityForName("Users", inManagedObjectContext: self.managedObjectContext)
let newUser = Users(entity: entity!, insertIntoManagedObjectContext: self.managedObjectContext)
if self.arrayAddedUsers.contains(usersFromParseDataBase[i].username){
// Saving new records in Core Data
}
}
})
})
dispatch_async(queue, { () -> Void in
self.getObjectsFromQueryWithDescendingOrder("Group", key: "membersUsername", value: userName, descendingOrder: "conversationUpdate", completionHandler: { (objects4) -> Void in
if array.count == 2 {
// Getting data in background - photo.getDataInbackgroundWithBlock
}
}else{
// Getting data in background - photo.getDataInbackgroundWithBlock
}
}
})
})
dispatch_barrier_async(queue, { () -> Void in
// Doing some stuff in background which needs the data from threads above
})
}else{
// Print error from loginWithUsernaemInBackground
}
}
}
}
问题是,我需要这些数据用于以后的其他操作。我的代码不一致。我认为你的思路是对的。当我创建一个简单的程序并使用
dispatch\u barrier\u async
时,它可以完美地工作:
let queue = dispatch_queue_create("com.karagan.app.queue", DISPATCH_QUEUE_CONCURRENT)
dispatch_async(queue, { () -> Void in
sleep(1)
print("1")
})
dispatch_async(queue, { () -> Void in
sleep(2)
print("2")
})
dispatch_async(queue, { () -> Void in
sleep(3)
print("3")
})
dispatch_async(queue, { () -> Void in
sleep(4)
print("4")
})
dispatch_barrier_async(queue, { () -> Void in
print("done")
})
输出:
1
2
3
4
done
我认为问题在于dispatch\u async
没有等待调用PFFile.getDataInBackgroundithBlock
完成:
photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
self.arrayImageFiles.append(imageData!)
print("Loading group image")
}
})
尝试将所有调用切换到getdatainbackgroundithblock
,而改为同步调用PFFile.getData
(:):
这实际上不应该有任何性能问题,因为您已经在异步执行此代码。您可能需要查看dispatch\u group\u create()、dispatch\u group\u wait()和dispatch\u group\u async(),以便获得一组要在继续之前等待完成的任务。此链接可能会有所帮助:如果要分派的代码块本身是异步任务,则可能必须显式地
dispatch\u group\u enter
/离开
。如果不查看生成这些日志消息的代码,就很难诊断问题或进一步提出建议。或者,坦率地说,因为您的代码非常复杂,您可能希望构造一个能够体现您所描述的bug类型的代码。你好,Rob,我添加了一个简单版本的代码,其中只包含最重要的部分。它全面吗?如果没有,我可以试着简化。谢谢你的帮助。dee zg,我已经试过调度组创建()。。。但我还是有同样的问题。只是我不知道如何正确地实现它。我总是遇到同样的问题,除非我在最后一个区块中添加“sleep(Uint32)”,但这并不一致。如果有人找到了我问题的解决方案,我会非常感激,因为已经有3-4周的时间了,我一直在解决这个问题,不幸的是,关于堆栈溢出的任何问题都没有帮助。谢谢Mark的回答。我还需要做一些测试,但这可能会对我有所帮助。我不知道可以在主线程上加载图像数据。我非常感谢您的帮助,如果它真的解决了我的问题,我会通知您。如果以前提交到同一队列的任务是同步的,则使用调度\u barrier\u async
只能用作“哨兵”。但在OPs中,它们是异步的。也就是说,调用立即返回,对于队列,此块已完成。@CouchDeveloper这就是我在回答中所说的,也是我建议同步这些任务的原因。我遗漏了什么吗?网络请求不应同步执行。一种可行的方法是使用@dezg在其对OPs问题的评论中建议的调度组。链接指出的答案是正确的,并且解释得很好。因此,在这种情况下,由于网络调用是在异步块中完成的,因此不应该冻结UI,但它将强制每个块中的图像等待加载同一块中的前一个图像。
photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
self.arrayImageFiles.append(imageData!)
print("Loading group image")
}
})
var imageData = photoFile.getData
if (imageData != nil) {
self.arrayImageFiles.append(imageData!)
}