gpt4 book ai didi

ios - 如何管理下载队列?

转载 作者:搜寻专家 更新时间:2023-11-01 06:32:14 24 4
gpt4 key购买 nike

我正在接受用户输入以从服务器下载文件。下载任务可能包括请求网络服务。

我期待这样的事情:

1) Whenever the user selects a file to download or requesting for web service, then it should be treated as one block of operation or task and should go in the queue which will be managed globally at the app level.
2) At the same time if the queue is empty then it should automatically start executing the current task.
3) If queue contains any operation then it should execute all old operation in synchronously then execute the last one.

任何人都可以建议如何通过优化的方式完成这项工作吗?

看看我尝试了什么:

class func downloadChaptersFromDownloadQueue() {

let gbm = GlobalMethods()

for chapterDetail in gbm.downloadOpertationQueue.array.enumerated() {

if chapterDetail.element.chapterdata.state == .non || chapterDetail.element.chapterdata.state == .paused || chapterDetail.element.chapterdata.state == .downloading {

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .downloading
let s = DispatchSemaphore(value: 0)

self.downloadActivty(courseId: chapterDetail.element.courseId, mod: chapterDetail.element.chapterdata, selectedIndexpath: chapterDetail.element.cellForIndexpath, success: { (result) in

if (result) {
if (WC_SQLite.shared.updateChapterState(courseId: chapterDetail.element.courseId, chapterId: chapterDetail.element.chapterdata.id, state: .downloaded)) {
s.signal()

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .downloaded
NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": 1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
else {
s.signal()
gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .non
NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": -1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
}
else {
_ = WC_SQLite.shared.updateChapterState(courseId: chapterDetail.element.courseId, chapterId: chapterDetail.element.chapterdata.id, state: .non)

s.signal()

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .non
NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": -1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
})
s.wait()
}
}
}

最佳答案

创建一个异步队列。首先使用调度组跟踪完成了多少请求,并在所有请求完成时收到通知(完全异步)。

接下来,将您的所有请求排队。每个请求都应该有一个唯一的标识符,以便您知道哪个请求已完成或失败(您的情况下的 chapterId 和 pageNumber 应该足够了)。

一次执行所有请求(同样是异步的),当每个请求完成时(通过完成 block 在主队列上),您将收到通知。应使用所有请求响应及其唯一标识符调用完成 block 。

例子:

class NetworkResponse {
let data: Data?
let response: URLResponse?
let error: Error?

init(data: Data?, response: URLResponse?, error: Error?) {
self.data = data
self.response = response
self.error = error
}
}


class NetworkQueue {
static let instance = NetworkQueue()
private let group = DispatchGroup()
private let lock = DispatchSemaphore(value: 0)
private var tasks = Array<URLSessionDataTask>()
private var responses = Dictionary<String, NetworkResponse>()

private init() {

}

public func enqueue(request: URLRequest, requestID: String) {

//Create a task for each request and add it to the queue (we do not execute it yet). Every request that is created, we enter our group.

self.group.enter();
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

//Only one thread can modify the array at any given time.
objc_sync_enter(self)
self.responses.updateValue(NetworkResponse(data: data, response: response, error: error), forKey: requestID)
objc_sync_exit(self)

//Once the request is complete, it needs to leave the group.
self.group.leave()
}

//Add each task to the queue.
self.tasks.append(task)
}

public func execute(completion: @escaping (_ responses: Dictionary<String, NetworkResponse>) -> Void) {

//Get notified on the main queue when every single request is completed (they all happen asynchronously, but we get one notification)

self.group.notify(queue: DispatchQueue.main) {

//Call our completion block with all the responses. Might be better to use a sorted dictionary or something here so that the responses are in order.. but for now, a Dictionary with unique identifiers will be fine.
completion(self.responses)
}

//Execute every task in the queue.
for task in self.tasks {
task.resume()
}

//Clear all executed tasks from the queue.
self.tasks.removeAll()
}
}

编辑(使用您自己的代码):

class func downloadChaptersFromDownloadQueue() {


let gbm = GlobalMethods()
let group = DispatchGroup()
let lock = NSLock()

//Get notified when ALL tasks have completed.
group.notify(queue: DispatchQueue.main) {
print("FINISHED ALL TASKS -- DO SOMETHING HERE")
}

//Initially enter to stall the completion
group.enter()

defer {
group.leave() //Exit the group to complete the enqueueing.
}

for chapterDetail in gbm.downloadOpertationQueue.array.enumerated() {

if chapterDetail.element.chapterdata.state == .non || chapterDetail.element.chapterdata.state == .paused || chapterDetail.element.chapterdata.state == .downloading {

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .downloading

//Enter the group for each downloadOperation
group.enter()

self.downloadActivty(courseId: chapterDetail.element.courseId, mod: chapterDetail.element.chapterdata, selectedIndexpath: chapterDetail.element.cellForIndexpath, success: { (result) in

lock.lock()
defer {
group.leave() //Leave the group when each downloadOperation is completed.
}

if (result) {
if (WC_SQLite.shared.updateChapterState(courseId: chapterDetail.element.courseId, chapterId: chapterDetail.element.chapterdata.id, state: .downloaded)) {

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .downloaded
lock.unlock()

NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": 1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
else {
gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .non
lock.unlock()

NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": -1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
}
else {
_ = WC_SQLite.shared.updateChapterState(courseId: chapterDetail.element.courseId, chapterId: chapterDetail.element.chapterdata.id, state: .non)

gbm.downloadOpertationQueue[chapterDetail.offset].chapterdata.state = .non
lock.unlock()

NotificationCenter.default.post(name: NSNotification.Name(("DownloadChapter")), object: self, userInfo: ["progress": -1.0, "notifIdentifier":(chapterDetail.element.cellForIndexpath)])
}
})
}
}
}

同样,这是异步的,因为您不希望用户永远等待下载 100 个页面..

关于ios - 如何管理下载队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45549273/

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