使用 Swift 3 中的 DispatchGroup() 来执行任务?
Using DispatchGroup() in Swift 3 to perform a task?
使用 Swift 3,使用 GCD 已更改为 DispatchGroup()
,我正在努力学习在我的代码中使用它。
目前我在另一个 class 中有一个函数尝试下载文件并输出其速度。我喜欢先完成该功能,因为我将其速度分配给 var
,我将在第一个 class 中使用它来执行依赖于该 var
的其他任务。
事情是这样的:
第二个class:
func checkSpeed()
{
// call other functions and perform task to download file from link
// print out speed of download
nMbps = speedOfDownload
}
第一个Class:
let myGroup = DispatchGroup()
let check: SecondClass = SecondClass()
myGroup.enter()
check.checkSpeed()
myGroup.leave()
myGroup.notify(queue: DispatchQueue.main, execute: {
print("Finished all requests.")
print("speed = \(check.nMbps)")
})
问题是 Finish all requests
先得到输出,因此 speed
返回 nil
,然后 checkSpeed
完成并输出正确的下载速度。
我相信我做错了,但我不确定?
第一个class完成checkSpeed
后如何保证speed
得到正确的值?
checkSpeed
的详细信息与 GitHub 中的 connectedToNetwork
完全相同:connectedness.swift
在此处找到的评论和解决方案中提供了提示:,因为我只执行一个任务,所以我使用了异步完成处理程序:
第二个Class:
func checkSpeed(completion: @escaping () -> ())
{
// call other functions and perform task to download file from link
// print out speed of download
nMbps = speedOfDownload
completion()
}
第一个Class:
let check: SecondClass = SecondClass()
check.checkSpeed {
print("speed = \(check.nMbps)")
}
现在 checkSpeed
将首先完成并为 speed
分配适当的值。
您需要在输入的任务完成后调用DispatchGroup.leave()
。因此,在您的代码中,myGroup.leave()
需要放在 checkSpeed()
方法内完成处理程序的末尾。
您可能需要像这样修改您的代码:
func checkSpeed(in myGroup: DispatchGroup) {
//...
...downLoadTask... {...its completion handler... in
//...
// print out speed of download
nMbps = speedOfDownload
myGroup.leave() //<- This needs to be placed at the end of the completion handler
}
//You should not place any code after invoking asynchronous task.
}
并将其用作:
myGroup.enter()
check.checkSpeed(in: myGroup)
myGroup.notify(queue: DispatchQueue.main, execute: {
print("Finished all requests.")
print("speed = \(check.nMbps)")
})
但是,正如 vadian 的评论或盘古的回答中所述,您通常不会将 DispatchGroup
用于单个异步任务。
加法
我要说,我强烈推荐completion handler pattern盘古的回答。这是处理异步任务的更通用的方法。
如果您已按照建议将 checkSpeed()
修改为 checkSpeed(completion:)
,您可以像这样轻松地试验 DispatchGroup
:
let myGroup = DispatchGroup()
let check: SecondClass = SecondClass()
let anotherTask: ThirdClass = ThirdClass()
myGroup.enter() //for `checkSpeed`
myGroup.enter() //for `doAnotherAsync`
check.checkSpeed {
myGroup.leave()
}
anotherTask.doAnotherAsync {
myGroup.leave()
}
myGroup.notify(queue: DispatchQueue.main) {
print("Finished all requests.")
print("speed = \(check.nMbps)")
}
使用 Swift 3,使用 GCD 已更改为 DispatchGroup()
,我正在努力学习在我的代码中使用它。
目前我在另一个 class 中有一个函数尝试下载文件并输出其速度。我喜欢先完成该功能,因为我将其速度分配给 var
,我将在第一个 class 中使用它来执行依赖于该 var
的其他任务。
事情是这样的:
第二个class:
func checkSpeed()
{
// call other functions and perform task to download file from link
// print out speed of download
nMbps = speedOfDownload
}
第一个Class:
let myGroup = DispatchGroup()
let check: SecondClass = SecondClass()
myGroup.enter()
check.checkSpeed()
myGroup.leave()
myGroup.notify(queue: DispatchQueue.main, execute: {
print("Finished all requests.")
print("speed = \(check.nMbps)")
})
问题是 Finish all requests
先得到输出,因此 speed
返回 nil
,然后 checkSpeed
完成并输出正确的下载速度。
我相信我做错了,但我不确定?
第一个class完成checkSpeed
后如何保证speed
得到正确的值?
checkSpeed
的详细信息与 GitHub 中的 connectedToNetwork
完全相同:connectedness.swift
在此处找到的评论和解决方案中提供了提示:
第二个Class:
func checkSpeed(completion: @escaping () -> ())
{
// call other functions and perform task to download file from link
// print out speed of download
nMbps = speedOfDownload
completion()
}
第一个Class:
let check: SecondClass = SecondClass()
check.checkSpeed {
print("speed = \(check.nMbps)")
}
现在 checkSpeed
将首先完成并为 speed
分配适当的值。
您需要在输入的任务完成后调用DispatchGroup.leave()
。因此,在您的代码中,myGroup.leave()
需要放在 checkSpeed()
方法内完成处理程序的末尾。
您可能需要像这样修改您的代码:
func checkSpeed(in myGroup: DispatchGroup) {
//...
...downLoadTask... {...its completion handler... in
//...
// print out speed of download
nMbps = speedOfDownload
myGroup.leave() //<- This needs to be placed at the end of the completion handler
}
//You should not place any code after invoking asynchronous task.
}
并将其用作:
myGroup.enter()
check.checkSpeed(in: myGroup)
myGroup.notify(queue: DispatchQueue.main, execute: {
print("Finished all requests.")
print("speed = \(check.nMbps)")
})
但是,正如 vadian 的评论或盘古的回答中所述,您通常不会将 DispatchGroup
用于单个异步任务。
加法
我要说,我强烈推荐completion handler pattern盘古的回答。这是处理异步任务的更通用的方法。
如果您已按照建议将 checkSpeed()
修改为 checkSpeed(completion:)
,您可以像这样轻松地试验 DispatchGroup
:
let myGroup = DispatchGroup()
let check: SecondClass = SecondClass()
let anotherTask: ThirdClass = ThirdClass()
myGroup.enter() //for `checkSpeed`
myGroup.enter() //for `doAnotherAsync`
check.checkSpeed {
myGroup.leave()
}
anotherTask.doAnotherAsync {
myGroup.leave()
}
myGroup.notify(queue: DispatchQueue.main) {
print("Finished all requests.")
print("speed = \(check.nMbps)")
}