使用 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)")
}