В Swift, как я могу гарантировать, что только 1 задача выполняется / ожидает большую часть времени?

#swift

#swift

Вопрос:

В Swift у меня есть рекурсивная функция, которую я хочу, чтобы она выполнялась каждую минуту. Это выглядит примерно так, как показано ниже.

 func someFunc() {
    // business logics...
    DispatchQueue.global().asyncAfter(deadline: .now()   60) {
        self.someFunc()
    }
}
 

Дело в том, что это someFunc() может быть инициировано несколькими вызывающими абонентами, но я хочу разрешить только один экземпляр someFunc(), запущенный или ожидающий выполнения в будущем.

Каков наилучший способ гарантировать, что не более 1 someFunc() будет запущено или поставлено в очередь в любой момент времени?

(Я использую Swift 5.3)

Ответ №1:

Вы также можете использовать NSLock для этого:

 import PlaygroundSupport

let lock = NSLock()

func someFunc(msg: String) {
  guard lock.try() else { return }
  print(msg)
  DispatchQueue.global().asyncAfter(deadline: .now()   5) {
    lock.unlock()
    someFunc(msg: msg)
  }
}

someFunc(msg: "call1")
someFunc(msg: "call2") // Ignored
someFunc(msg: "call3") // Ignored

PlaygroundPage.current.needsIndefiniteExecution = true
 

Ответ №2:

Вы можете использовать логическое значение для отслеживания того, что вызов функции находится в очереди (при условии, что вы не вызываете someFunc() из разных потоков)

 var isQueued = false
func someFunc() {
    if isQueued { return }
    // business logics...

    isQueued = true
    DispatchQueue.global().asyncAfter(deadline: .now()   60) {
        self.isQueued = false
        self.someFunc()
    }
}
 

Пример

 class Example {
    var isQueued = false
    func someFunc(_ i: Int) {
        if isQueued { return }
        // business logics...
        if i > 500 {
            return
        }
        print(i)

        isQueued = true
        DispatchQueue.global().asyncAfter(deadline: .now()   1) {
            self.isQueued = false
            self.someFunc(i * 10)
        }
    }
}

let t = Example()
t.someFunc(1)
sleep(2)
t.someFunc(2)
sleep(1)
t.someFunc(3)
sleep(1)
t.someFunc(4)
sleep(1)
t.someFunc(5)
 

С принтами

1
10
100
4
40
400