gpt4 book ai didi

swift - 带有完成处理程序的异步调用上的多个 URLSession dataTask 会导致内存增加

转载 作者:行者123 更新时间:2023-11-30 10:50:55 24 4
gpt4 key购买 nike

我正在快速开发一个上传项目。我正在使用 imagepickercontroller 获取非常大的文件(大小超过 500 MB 的视频、图片),并将该文件分成大小为 1 MB 的 block 。然后我将这些 block 发送到远程服务器并在服务器中对它们进行碎片整理,然后向用户显示该文件。

如果文件大小低于 300 MB,我没有问题。但是在这个大小之后,内存增加太多并且应用程序崩溃。实际上,在每种情况下,内存使用量都会增加,但不会发生崩溃。

当我在控制台上查看进度时,我看到 URLSession 任务开始。但是,由于这些任务正在等待完成处理程序的响应,因此任务队列不断增长,内存使用量不断增加。有没有办法在任务开始时,该任务的完成处理程序也开始?我想如果我可以同时释放任务队列,我的问题就解决了。我正在等待你的帮助。

let url:URL = URL(string: "\(addressPrefix)UploadFile")!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
request.httpMethod = "POST"

let bodyData = "\(metaDataID)~\(chunkIndex)~\(chunkSize)~\(chunkHash)~\(wholeTicket)~\(fileDataString)"

request.httpBody = bodyData.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue));
request.timeoutInterval = .infinity

let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
guard let _:Data = data, let _:URLResponse = response, error == nil else {
var attemptCounter = 1
if attemptCounter <= 3 {
completion("\(attemptCounter).attempt",chunkSize, error)
attemptCounter += 1
}
return
}
let jsonStr = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
completion(jsonStr, chunkSize, error)
SingletonConnectionManager.sharedConnectionDataManager.dataTasks["uploadFile"] = nil
})
SingletonConnectionManager.sharedConnectionDataManager.dataTasks["uploadFile"] = task
task.resume()

---我从 tableview Controller 中的这个函数调用这个 URLSession 任务

 tmpConnection.uploadFile(chunk, metaDataID!, chunkIndex: chunkIndex, completion: {(result, chunkSize, error) in
// I want to enter immediately when 'uploadFile' get called })

最佳答案

请求实际上并没有等到所有请求都发送完毕。当事情正常工作时,每个回调都会在关联的请求完成时发生,并且更快地发生是没有意义的,因为回调提供了来自服务器的响应(在请求完成之前您不可能返回该响应)已全部发出)。

这里的问题是,您通过同时启动太多任务而完全堵塞了 session 。 NSURLSession 中有一个已知的错误,当您在单个 session 中同时创建大量任务时,该错误会导致它开始崩溃。当您在 session 中获得太多任务时,IIRC, session 完全停止调用回调,并且基本上 session 变得不可用。 (几年前还有另一个 Stack Overflow 问题讨论过这个问题,尽管我现在似乎找不到它。)

由于任务永远不会完成,您的应用最终会泄漏用于正文数据的所有内存,这意味着您的应用只会分配越来越多的内存,直到被逐出。

解决此问题的唯一方法是停止一次将所有请求添加到 session 中。首先启动几个任务(最多八个部分左右),然后等待发送下一个部分,直到前面的部分之一完成或失败。这种方法不仅可以防止您破坏 NSURLSession,还可以防止您分配大量内存来保存所有请求主体 NSData 对象,这些对象当前都同时位于 RAM 中。

我建议保留一个 NSNumber 对象的 NSMutableArray 来表示每个未发送的 block 。这样,您就知道还剩下什么要发送,并且可以循环到 8 并取出前 8 个数字,然后发送包含这些数字的 block 。当请求成功完成时,从数组中获取下一个数字并发送包含该数字的 block 。

此外,您不应在重试特定次数后停止。相反,当请求失败时,检查失败情况以决定是重试(网络故障)还是放弃(服务器错误)。然后使用reachability等待合适的时机再试,当它说目的主机可达时再试。仅当用户明确要求您通过点击取消按钮或类似按钮取消上传时,才取消上传。如果用户要求您取消上传,请拆除您的数据结构,这样您就不会启动任何新请求,然后使 URL session 无效。

关于swift - 带有完成处理程序的异步调用上的多个 URLSession dataTask 会导致内存增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54550227/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com