![](/img/trans.png)
[英]Retrying a failed download in URLSession:task:didCompleteWithError
[英]GCD: URLSession download task
我需要下载大量文件 - 以前一次只能下载一个文件。 当前的设计是这样的,当用户下载单个文件时,将创建一个 URLSession 任务,并使用 urlsession 的委托方法记录进度/完成/失败。 我的问题是,如何在此委托方法中离开调度组? 我需要一次下载 10 个文件,在前 10 个完成后开始下 10 个。 现在,如果我在委托方法中离开调度组,调度组将永远等待。 以下是我目前实施的内容:
self.downloadAllDispatchQueue.async(execute: {
self.downloadAllDispatchGroup = DispatchGroup()
let maximumConcurrentDownloads: Int = 10
var concurrentDownloads = 0
for i in 0..<files.count
{
if self.cancelDownloadAll {
return
}
if concurrentDownloads >= maximumConcurrentDownloads{
self.downloadAllDispatchGroup.wait()
concurrentDownloads = 0
}
if let workVariantPart = libraryWorkVariantParts[i].workVariantPart {
concurrentDownloads += 1
self.downloadAllDispatchGroup.enter()
//call method for download
}
}
self.downloadAllDispatchGroup!.notify(queue: self.downloadAllDispatchQueue, execute: {
DispatchQueue.main.async {
}
})
})
在代表中:
func downloadDidFinish(_ notification: Notification){
if let dispatchGroup = self.downloadAllDispatchGroup {
self.downloadAllDispatchQueue.async(execute: {
dispatchGroup.leave()
})
}
}
这可能吗? 如果没有,我怎样才能做到这一点?
如果downloadAllDispatchQueue
是串行队列,则您问题中的代码将死锁。 当您调用wait
时,它会阻塞当前线程,直到它收到来自另一个线程的leave
调用。 如果您尝试将leave
分派到已被wait
调用阻塞的串行队列,它将死锁。
解决方案是根本不将leave
分派到队列中。 没有那个必要。 只需从当前线程直接调用它:
func downloadDidFinish(_ notification: Notification) {
downloadAllDispatchGroup?.leave()
}
在下载大量文件的时候,我们经常会用到一个后台session,详见后台下载文件。 我们这样做是为了在用户离开应用程序后继续下载。
当你开始使用后台 session 时,就不需要引入这种“batches of 10”的逻辑了。 后台session为您管理所有这些请求。 在“十个批次”逻辑上分层只会引入不必要的复杂性和低效率。
相反,我们只是实例化一个单一的后台 session 并提交所有请求,让后台 session 从那里管理请求。 它简单、高效,并且即使在用户离开应用程序后也能继续下载。 如果您下载的文件太多以至于您觉得需要像这样管理它们,那么最终用户很可能会对这个过程感到厌倦,并且可能希望在请求完成时离开应用程序去做其他事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.