Как приостановить работу очереди в Swift - PullRequest
1 голос
/ 09 октября 2019

У меня есть пара операций на устройстве IoT из приложения iOS. Так что все мои операции находятся в OperationsQueue с последовательными операциями.

Здесь я хочу выполнять одну операцию за раз, и каждая операция должна ждать, пока я не получу ответ от устройства IoT.

Здесь ответ устройства IoT займет время для отправки обратно. так как ждать текущей операции в очереди операций, пока я не получу ответ от IoT.

Итак, есть ли способ приостановить текущую запущенную операцию до получения ответа от IoT, а затем я возобновлю ее, чтобы началась следующая операция в очереди операций.

Я пытался работать в спящем режиме, но это требовало времени, но мы не можем гарантировать ответ устройства IoT.

Любые предложения будут признательны. Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 09 октября 2019

Основная идея заключается в том, что вы не делаете паузу (или ждете, или спите), а скорее определяете «параллельную» операцию (см. Обсуждение параллельных операций в документации ), которая не делаетзапускать isFinished KVO до тех пор, пока устройство не ответит.

Простой способ сделать это - написать класс параллельных операций, такой как , показанный в этом ответе ,Тогда ваша операция IoT может создать подкласс этого AsynchronousOperation класса и просто вызвать finish(), когда устройство ответит.

Затем ваша очередь операций (которая предположительно имеет maxConcurrentOperationCount из 1 или, возможно, используетзависимостей), не запустит операцию до завершения предыдущей операции.

1 голос
/ 10 октября 2019

Вы можете использовать DispatchQueue и вызывать .suspend() при отправке операции, и иметь код, который получает ответный вызов .resume(). Затем, где бы вы ни хотели дождаться ответа, прежде чем продолжить, просто поставьте фиктивный queue.sync({ print("done waiting")}), и он автоматически будет ждать, пока не будет вызван .resume(), прежде чем печатать и продолжать.

import Dispatch
var queue = DispatchQueue(label: "queue")

func sendOperationToIoTDevice(){
    //send the operation
    //...
    queue.suspend()
}

...

//whatever code gets the response:
    //get response
    //...
    queue.resume()

...

//main code

sendOperationToIoTDevice()
queue.sync { print("done waiting") } // will hang here until .resume() is called
1 голос
/ 09 октября 2019

Как сказал Роб , вы можете реализовать класс асинхронных операций и подкласс из него свою операцию IoT . Для меня это выглядит как наиболее предпочтительный способ реализации вашего дела.

В качестве альтернативы , если вам нужно продолжить процесс только после завершения какого-либо асинхронного события в другом потоке, вы можете использовать NSCondition . Это механизм от obj-c, который обеспечивает простой способ ожидания возникновения условия.

Вот пример:


let cond = NSCondition()
var available = false
var SharedString = ""

class WriterThread : Thread {

    override func main(){
        for _ in 0..<5 {
            cond.lock()
            SharedString = "?"
            available = true
            cond.signal() // Notify and wake up the waiting thread/s
            cond.unlock()
        }
    }
}

class PrinterThread : Thread {

    override func main(){
        for _ in 0..<5 { //Just do it 5 times
            cond.lock()
            while(!available){   //Protect from spurious signals
                cond.wait()
            }
            print(SharedString)
            SharedString = ""
            available = false
            cond.unlock()
        }
    }
}

let writet = WriterThread()
let printt = PrinterThread()
printt.start()
writet.start()

...