ios swift中的并发任务执行

Posted

技术标签:

【中文标题】ios swift中的并发任务执行【英文标题】:Concurrent task execution in ios swift 【发布时间】:2018-10-09 05:17:44 【问题描述】:

我有一个包含消息 ID 的数组。通过将这些 id 传递给一个方法,我可以使用批处理请求从谷歌服务器获取消息/电子邮件。它适用于数百个 id 传递,但问题是当有数千个 Id 时,它需要更多时间来获取消息。所以为了避免这种情况,我决定同时执行任务。我集成的谷歌客户端库是 https://github.com/google/google-api-objectivec-client-for-rest/wiki 。对于 messagesGet.query 参考是 http://cocoadocs.org/docsets/GoogleAPIClientForREST/1.2.0/Classes/GTLRGmailQuery_UsersMessagesGet.html 。批量请求参考https://developers.google.com/gmail/api/guides/batch。

   var messageIDes = [AnyObject]() //143b3e9751e6b3fd,141c2194fb6e4d6d...thousands if Ids
func fetchingMessagesWithIDs()

    let batchQuery = GTLRBatchQuery()
    for eachID in messageIDes
    let query = GTLRGmailQuery_UsersMessagesGet.query(withUserId: "me", identifier: eachID as! String)
    query.fields = "id,labelIds, payload(headers, parts )"
    batchQuery.addQuery(query)
    
    service.executeQuery(batchQuery)  (ticket:GTLRServiceTicket, object:Any?, error:Error?) in
        if error == nil
            print("Object is \(String(describing: object))") //Contains Full mail Body
        
    

上述过程需要时间来避免我将数组分成大小为 100 的子数组并传递。

extension Array 
func divideBy(by size: Int) -> [[Element]] 
    return stride(from: 0, to: self.count, by: size).map 
        Array(self[$0..<Swift.min($0 + size, self.count)])
    

然后使用 dispatchQueue 并发执行我想获取消息但对结果不满意。

    var msgIDBatches = [[String]]()
func DividingMsgIdsandPassing()
    self.msgIDBatches = self.messageIDes.divideBy(by: 100) as! [[String]] //array inside subarray of size 100 elements.
    DispatchQueue.concurrentPerform(iterations: msgIDBatches.count)  (index) in
        for subArray in msgIDBatches
            let batchQuery = GTLRBatchQuery()
            for messageID in subArray 
                let query = GTLRGmailQuery_UsersMessagesGet.query(withUserId: "me", identifier: messageID as! String)
                query.fields = "id,labelIds, payload(headers, parts )"
                batchQuery.addQuery(query)
            
            service.executeQuery(batchQuery)  (ticket:GTLRServiceTicket, object:Any?, error:Error?) in
                if error == nil
                    print("Object is \(String(describing: object))") //Contains Full mail Body
                
            
        
    

我是否遵循正确的并发方法。任何其他获取逻辑都会有很大帮助。在这个答案中,有人告诉一个线程获取 ids 和 4 个线程获取消息。我如何使用 4 个线程来实现它。

【问题讨论】:

分割方法帮了我???? 【参考方案1】:

至于上面的代码,结果是否重复?如果是这样,我认为问题出在逻辑上:

DispatchQueue.concurrentPerform(iterations: msgIDBatches.count)  (index) in
    for subArray in msgIDBatches
        let batchQuery = GTLRBatchQuery()
        for messageID in subArray 
            let query = GTLRGmailQuery_UsersMessagesGet.query(withUserId: "me", identifier: messageID as! String)
            query.fields = "id,labelIds, payload(headers, parts )"
            batchQuery.addQuery(query)
        
        service.executeQuery(batchQuery)  (ticket:GTLRServiceTicket, object:Any?, error:Error?) in
            if error == nil
                print("Object is \(String(describing: object))") //Contains Full mail Body
            
        
    

既然您已经告诉调度队列迭代“msgIDBatches.count”次,那么在您的内部代码中,您应该只通过带有“index”的下标直接检索“subArray”一次:

DispatchQueue.concurrentPerform(iterations: msgIDBatches.count)  (index) in
    let subArray = msgIDBatches[index]
    let batchQuery = GTLRBatchQuery()
    for messageID in subArray 
        let query = GTLRGmailQuery_UsersMessagesGet.query(withUserId: "me", identifier: messageID as! String)
        query.fields = "id,labelIds, payload(headers, parts )"
        batchQuery.addQuery(query)
    
    service.executeQuery(batchQuery)  (ticket:GTLRServiceTicket, object:Any?, error:Error?) in
        if error == nil
            print("Object is \(String(describing: object))") //Contains Full mail Body
        
    

【讨论】:

以上是关于ios swift中的并发任务执行的主要内容,如果未能解决你的问题,请参考以下文章

iOS(Swift) TaskProtocol异步任务队列

Swift新async/await并发模型中子任务取消不能被其它子任务感知的原因及解决

Swift新async/await并发模型中子任务取消不能被其它子任务感知的原因及解决

Swift 中的 JSON 解析(iOS)

如何在 Swift 中测量 DispatchQueue 并发异步中的代码块执行时间?

高并发任务执行时间短的业务怎样使用线程池?并发不高任务执行时间长的业务怎样使用线程池?并发高业务执行时间长的业务怎样使用线程池?