在执行另一个块之前执行所有后台线程
Execute all background threads before executing another block
我正在尝试在 Core Data 中加载照片,但这需要一些后台线程,所以碰巧我的对象在没有照片的情况下保存在 Core Data 中,我得到的照片是零。我的小组照片也是如此。
简而言之,在每次迭代时,我都会在 Core Data 中保存一个对象,而且保存速度比加载我的照片数据要快。
我尝试了信号量、屏障、组...但 none 有效。我当然做错了什么,但我不知道是什么。如果有人可以帮助我,我将不胜感激,我已经为同样的问题苦苦挣扎了 2 周。这是我的简化版代码,完整版可以在下面访问:
// 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
}
}
}
}
这是日志中显示的内容,因此您可以清楚地看到屏障在图片加载完成之前执行。
TEST 3 - interacting user has been saved to core data
Loading profile image
Loading profile image
Loading group image
Loading profile image
Loading profile image
9
5
Loading group image
Loading group image
Loading group image
Loading group image
问题是我需要这些数据用于以后的其他操作。我的代码不一致。
我认为您的方向是正确的。当我创建一个简单的程序并使用 dispatch_barrier_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_async
没有等待对 PFFile.getDataInBackgroundWithBlock
的调用完成:
photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
self.arrayImageFiles.append(imageData!)
print("Loading group image")
}
})
尝试将对 getDataInBackgroundWithBlock
的所有调用切换为对 PFFile.getData
(https://parse.com/docs/osx/api/Categories/PFFile%28Synchronous%29.html#/c:objc%28cs%29PFFile%28im%29getData:) 的同步调用:
var imageData = photoFile.getData
if (imageData != nil) {
self.arrayImageFiles.append(imageData!)
}
这应该不会有任何性能问题,因为您已经在异步执行此代码。
我正在尝试在 Core Data 中加载照片,但这需要一些后台线程,所以碰巧我的对象在没有照片的情况下保存在 Core Data 中,我得到的照片是零。我的小组照片也是如此。
简而言之,在每次迭代时,我都会在 Core Data 中保存一个对象,而且保存速度比加载我的照片数据要快。
我尝试了信号量、屏障、组...但 none 有效。我当然做错了什么,但我不知道是什么。如果有人可以帮助我,我将不胜感激,我已经为同样的问题苦苦挣扎了 2 周。这是我的简化版代码,完整版可以在下面访问:
// 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
}
}
}
}
这是日志中显示的内容,因此您可以清楚地看到屏障在图片加载完成之前执行。
TEST 3 - interacting user has been saved to core data
Loading profile image
Loading profile image
Loading group image
Loading profile image
Loading profile image
9
5
Loading group image
Loading group image
Loading group image
Loading group image
问题是我需要这些数据用于以后的其他操作。我的代码不一致。
我认为您的方向是正确的。当我创建一个简单的程序并使用 dispatch_barrier_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_async
没有等待对 PFFile.getDataInBackgroundWithBlock
的调用完成:
photoFile.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
self.arrayImageFiles.append(imageData!)
print("Loading group image")
}
})
尝试将对 getDataInBackgroundWithBlock
的所有调用切换为对 PFFile.getData
(https://parse.com/docs/osx/api/Categories/PFFile%28Synchronous%29.html#/c:objc%28cs%29PFFile%28im%29getData:) 的同步调用:
var imageData = photoFile.getData
if (imageData != nil) {
self.arrayImageFiles.append(imageData!)
}
这应该不会有任何性能问题,因为您已经在异步执行此代码。