如何停止正在进行的调度组执行并开始新的调度组?

问题描述 投票:0回答:1

所以我有一个分页 API,每次用户进入屏幕时我都必须调用它。下面的代码工作正常,但如果说 API 调用正在进行并且用户退出并再次返回,那么就会出现一个问题,而不是两个执行同时开始。 并且必须等待两个执行完成。 所以,我想要的是停止正在进行的 API 调用,并在请求新的 API 时启动新的 API 调用 如果此设置有任何错误,请通知我我做错了什么?

func storeAllData(matchID: Int64) {
        GlobalVariable.isFetchingData = true
        dbManager = DbManager.shared
        if let lastScore = dbManager.getLastBallForCurrentMatch(matchID: matchID) {
            self.fetchAllScore(scoreID: lastScore.id ?? 0, matchID: matchID)
        } else {
            self.fetchAllScore(scoreID: 0, matchID: matchID)
        }
    }
    
    func fetchAllScore(scoreID: Int = 0, matchID: Int64) {
        let id = matchID
        backgroundQueue.async { [self] in
            autoreleasepool {
                fetchPaginatedData(matchID:Int(id), scoreID: scoreID, page: 1)
                dispatchGroup.wait()
                print("All API calls finished")
            }
        }
    }
    
    func fetchPaginatedData(matchID: Int,scoreID: Int = 0, page: Int) {
        dispatchGroup.enter()
        MatchesNetworkManager.sharedInstance.getAllScore(matchID: Int64(matchID), scoreID: Int64(scoreID), page: Int64(page), completionHandler: { [weak self] (allSocre, isSuccess, errorStr) in
            
            if isSuccess {
                if allSocre?.match?.scores != nil {
                    self?.oldScores.append(contentsOf: ((allSocre?.match?.scores)!))
                    self?.backgroundQueue.async {
                        if let scores = allSocre?.match?.scores as? [Scores] {
                            self?.dbManager.insertRecords(matchID: matchID, records: scores)
                            DispatchQueue.main.async {
                                self?.oldScores = []
                                if allSocre?.page_num ?? 0 == 1 {
                                    self?.updateScoreView()
                                }
                                if (allSocre?.page_num ?? 0) < (allSocre?.total_pages ?? 0) {
                                    self?.fetchPaginatedData(matchID: matchID,page: (allSocre?.page_num ?? 1) + 1)
                                } else {
                                    // All pages have been fetched
                                    GlobalVariable.isFetchingData = false
                                    print("All API calls finished")
                                    NotificationCenter.default.post(name: .refreshMarketView, object: nil, userInfo: nil)
                                    self?.dispatchGroup.leave()
                                }
                            }
                        }
                    }
                } else {
                    self?.updateScoreView()
                    GlobalVariable.isFetchingData = false
                }
                
            } else {
                print("API call error: \(errorStr)")
                self?.updateScoreView()
                GlobalVariable.isFetchingData = false
                self?.dispatchGroup.leave()
            }
        })
    }

ios swift background grand-central-dispatch
1个回答
0
投票

这些(和类似)平台上大多数并发抽象的现实是,一旦启动,工作单元几乎完全无法被强制取消(除了终止进程)。

通常处理此问题的方法是检查工作单元本身的“内部”标志,表明它们应该被取消,此时它们可以执行任何需要的清理工作(如果有),并提前返回。如果您有一个调度组,则可以将一个标志与该组关联起来,然后在每个操作开始时(或在该操作内循环的每次迭代的顶部)显式检查该标志,如果该组则提前返回已取消。 您可以临时执行此操作。您可以使用现有的抽象(如

NSOperation

cancel
方法
),但即使在那里,您也会注意到 
Discussion
部分的第一行说:“此方法不会强制您的操作代码停止。”您的操作代码仍必须检查该标志。 例如,您可以使用

NSBlockOperation

,创建操作实例,然后捕获对执行实际工作的块的闭包内的

NSBlockOperation
实例的归零弱引用,然后使用该引用来检查是否
NSBlockOperation
已被取消(或解除分配)。
长话短说,天下没有免费的午餐。

© www.soinside.com 2019 - 2024. All rights reserved.