使用Swift 3中的DispatchGroup()执行任务?

时间:2016-12-17 21:09:32

标签: ios swift swift3 grand-central-dispatch

使用Swift 3,使用GCD已更改为DispatchGroup(),我试图学习在我的代码中使用它。

目前我在另一个类中有一个函数试图下载文件并输出其速度。我希望首先完成该功能,因为我将其速度分配给var,我将在第一个类中使用它来执行依赖于var的其他任务。

它是这样的:

第二课:

func checkSpeed()
{
    // call other functions and perform task to download file from link

    // print out speed of download

    nMbps = speedOfDownload
}

头等舱:

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首先输出,因此返回nil speed,然后checkSpeed完成并输出正确的下载速度。

我相信我做错了,但我不确定?

如何在第一堂课完成speed后确保checkSpeed获得正确的值?

checkSpeed的详细信息与GitHub中的connectedToNetwork完全相同:connectedness.swift

2 个答案:

答案 0 :(得分:7)

输入的任务完成后,您需要致电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的评论或Pangu的回答所述,您通常不会将DispatchGroup用于单个异步任务。

<强> ADDITION

我需要说,我强烈推荐Pangu的回答中显示的完成处理程序模式。它是处理异步任务的更通用方法。

如果您按照建议将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)")
}

答案 1 :(得分:2)

在此处的注释和解决方案中提供了提示:from @vadian,因为我只执行一项任务,所以我使用了异步完成处理程序:

第二课:

func checkSpeed(completion: @escaping () -> ())
{
    // call other functions and perform task to download file from link

    // print out speed of download

    nMbps = speedOfDownload
    completion()

}

头等舱:

let check: SecondClass = SecondClass()

check.checkSpeed {
print("speed = \(check.nMbps)")

}

现在checkSpeed将首先完成,并为speed分配适当的值。