Параллельное выполнение задачи в ios swift - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть массив, в котором содержатся идентификаторы сообщения. Передав эти идентификаторы методу, я могу получать сообщения / электронные письма с сервера Google, используя пакетный запрос. Он отлично работает при передаче сотен идентификаторов, но проблема в том, что при наличии тысяч идентификаторов требуется больше времени для получения сообщений. Поэтому, чтобы избежать этого, я решил выполнить задачу в одночасье. Клиентская библиотека Google, которую я интегрировал, составляет 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 Concurrent выполнять, я хочу получить сообщения, но не удовлетворен результатом.

    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
                }
            }
        }
    }
}

Следую ли я правильному подходу к параллелизму. Любая другая логика извлечения будет большой помощью. В этом ответе кто-то сказал один поток для получения идентификаторов и 4 потока для получения сообщений. Как я могу добиться этого, используя 4 темы.

1 Ответ

0 голосов
/ 28 апреля 2018

Что касается кода выше, дублируется ли результат? Если это так, я думаю, что проблема в логике:

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', то во внутреннем коде вы должны извлекать '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
        }
    }
}
...