ios - 信号量同步请求 Swift4 永远停止

标签 ios swift semaphore

我需要来自网络服务的同步请求,所以我使用 sempahore:

class func syncProducts() {
    print("syncProducts() 1")
    let idsLocal = getProductsIds()
    let semaphore = DispatchSemaphore(value: 0)
    var idsCloud : [Int] = []
    print("Getting cloud ids... 1")

    OdooService.getProductsIds { (params: [Int]) in
        print("SuccessBlock size ids: \(params.count)  1")
        idsCloud = params
        semaphore.signal()
    }

    semaphore.wait()
    print("Depois do GetproductsIds:  1")
}

但在这个例子中,应用程序永远保持锁定状态!请求永无止境。这是我从网络服务器请求数据并返回成功 block 的功能。

static func getProductsIds(successBlock: @escaping (_ params: [Int]) -> Void)  {
    // check odoo auth
    let dispatch = DispatchGroup()
    if( OdooAuth.uid == 0 ) {
        print("Odoo offline, tentando reconectar...")
        dispatch.enter()
        OdooAuth.reconnect(successBlock: { params in
            print("Reconectado com sucesso...")
            dispatch.leave()
        }, failureBlock: { params in
            print("Falha no ReAuth")
            return
        })
    }

    print("Start request from Odoo...")
    let fieldsProducts = ["id"]
    let options = [ "fields": fieldsProducts] as [String : Any]
    var idsList : [Int] = []
    let params = [OdooAuth.db, OdooAuth.uid, OdooAuth.password,"product.template","search_read",[],options] as [Any]

    AlamofireXMLRPC.request(OdooAuth.host2, methodName: "execute_kw", parameters: params).responseXMLRPC {
        (response: DataResponse<XMLRPCNode>) -> Void in
        switch response.result {
        case .success( _):
            print("Success to get Ids")
            let str = String(data: response.data!, encoding: String.Encoding.utf8) as String!
            let options = AEXMLOptions()
            let xmlDoc = try? AEXMLDocument(xml: (str?.data(using: .utf8))!,options: options)
            //print(xmlDoc!.xml)

            for child in (xmlDoc?.root["params"]["param"]["value"]["array"]["data"].children)! {
                for childValue in child["struct"].children {
                    let id = childValue["value"]["int"].value!
                    idsList.append(Int(id)!)
                    //print("Id: \(id)")
                }
            }

            successBlock(idsList)

            break

        case .failure(let error):
                print("Error to get Ids: \(error.localizedDescription)")
            break
        } // fim switch
    } // fim request
} // fim getProductsIds

我不知道信号量是否是执行此操作的最佳方式,但我需要同步请求!我试过像在 reauth 中那样使用 DispatchGroup(),但也不起作用。

最佳答案

我预计死锁是在主线程上调用 getProductsIds 回调的结果,该回调被信号量阻塞。据我所知,默认情况下 Alamofire 在主线程上调度回调,我希望 AlamofireXMLRPC 就是这种情况,因为它是 Alamofire 的包装器。

我强烈建议在异步操作期间不要阻塞主线程。

但是,如果出于任何非常好的原因您不能这样做,您将需要确保回调不会在主调度队列中被调度(因为主调度队列被阻塞等待信号)。 Alamofire 本身有一个 response 重载,允许指定运行回调的 DispatchQueue 对象。似乎 AlamofireXMLRPC 也有一个,所以我会尝试利用它并进行更改

AlamofireXMLRPC.request(OdooAuth.host2, methodName: "execute_kw", parameters: params)
               .responseXMLRPC {
     // process result
}

到:

AlamofireXMLRPC.request(OdooAuth.host2, methodName: "execute_kw", parameters: params)
               .responseXMLRPC(queue: DispatchQueue.global(qos: .background)) {
     // process result
}

我基于 github source code AlamofireXMLRPC,但之前没有使用过它,所以可能会有一些语法错误。但它应该为您指明正确的方向。尽管如此,我还是建议您不要阻塞线程(我重复一遍,但这确实非常重要)。

关于ios - 信号量同步请求 Swift4 永远停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49406624/

相关文章:

ios - CloudKit - 无法从 iCloud 检索数据

ios - 如何更改 UITableView Swift 3 中的分隔符高度?

ios - 如何从单独的非 UIViewController 类调用我的 ViewController 的方法

c - 信号量和共享内存

macos - Mac OS X 上的 POSIX 信号量 : sem_timedwait alternative

PHP 将 Base 64 数据解码为 jpeg 以在 Web 浏览器中查看

ios - 在模态视图 Controller 后面更改 View Controller

ios - iOS 应用程序可以读取/访问 SMS 文本吗?

ios - Swift 3:呈现弹出窗口时崩溃

macos - sem_open 在 Mac OS X 10.6.6 HFS+ 上为少于 64 个字符的名称设置 ENAMETOOLONG