Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

324
Visualizações
Bloque de notificación de DispatchGroup que se llama antes

Tengo un problema con el bloque de notificación de DispatchGroup que se llama al principio de mi aplicación e hice este ejemplo de patio de recreo para experimentar. Según la salida, a veces se llama incluso antes del primer .leave(). Siento que me estoy perdiendo algo obvio y ahora lo he mirado demasiado tiempo.

 let s = DispatchSemaphore(value: 1) let dg = DispatchGroup() func go() -> Void { for i in 1...2 { doWork(attemptNo: i, who: "Lily", secs: Double.random(in: 1.0...5.0)) doWork(attemptNo: i, who: "Emmie", secs: Double.random(in: 1.0...10.0)) doWork(attemptNo: i, who: "Wiley", secs: Double.random(in: 1.0...3.0)) } } func doWork(attemptNo: Int, who: String, secs: TimeInterval) -> Void { DispatchQueue.global().async { dg.enter() print("\(who) wants to work, will wait \(secs) seconds, attempt #\(attemptNo)") if s.wait(timeout: .now() + secs) == .timedOut { print("\(who) was denied. No soup for me! Task #\(attemptNo) not going to happen.") dg.leave() return } let workSecs = UInt32(Int.random(in: 1...3)) print("\(who) went to work for \(workSecs) seconds on task #\(attemptNo)") DispatchQueue.global().asyncAfter(deadline: .now() + TimeInterval(workSecs)) { print("\(who) is sliding down the dinosaur tail. Task #\(attemptNo) all done!") s.signal() dg.leave() } } } go() dg.notify(queue: .global(), execute: {print("Everyone is done.")})

Salida de muestra:

 Emmie wants to work, will wait 4.674405654828654 seconds, attempt #1 Lily wants to work, will wait 1.5898288206500877 seconds, attempt #1 Wiley wants to work, will wait 1.2182416407288 seconds, attempt #1 Lily wants to work, will wait 3.3225083978280647 seconds, attempt #2 Everyone is done. Wiley wants to work, will wait 2.801577828588925 seconds, attempt #2 Emmie wants to work, will wait 8.9696422949966 seconds, attempt #2 Lily went to work for 3 seconds on task #2 Wiley was denied. No soup for me! Task #1 not going to happen. Lily was denied. No soup for me! Task #1 not going to happen. Wiley was denied. No soup for me! Task #2 not going to happen. Lily is sliding down the dinosaur tail. Task #2 all done! Emmie went to work for 3 seconds on task #1 Emmie is sliding down the dinosaur tail. Task #1 all done! Emmie went to work for 2 seconds on task #2 Emmie is sliding down the dinosaur tail. Task #2 all done!

En este caso, "todos han terminado" ocurre casi de inmediato y, dado que .leave son junto con no obtener el semáforo o después de que se realiza el "trabajo", esto no tiene sentido. Ayuda por favor.

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Su principal problema es que llama a dg.enter() en el lugar equivocado. Siempre desea llamar a enter() antes de la llamada asíncrona y desea llamar a leave() cuando finaliza la llamada asíncrona.

Como su código está escrito ahora, el ciclo for finaliza antes de que se realice la primera llamada para enter , por lo que la notify se activa de inmediato.

 func doWork(attemptNo: Int, who: String, secs: TimeInterval) -> Void { dg.enter() DispatchQueue.global().async { print("\(who) wants to work, will wait \(secs) seconds, attempt #\(attemptNo)") if s.wait(timeout: .now() + secs) == .timedOut { print("\(who) was denied. No soup for me! Task #\(attemptNo) not going to happen.") dg.leave() return } let workSecs = UInt32(Int.random(in: 1...3)) print("\(who) went to work for \(workSecs) seconds on task #\(attemptNo)") sleep(workSecs) print("\(who) is sliding down the dinosaur tail. Task #\(attemptNo) all done!") s.signal() dg.leave() } }

Su código también hace un uso extraño de un semáforo y el sueño. Supongo que este es un intento de simular un proceso en segundo plano de larga ejecución.

over 4 years ago · Santiago Trujillo Relatório

0

Así de sencillo, doWork vuelve antes de entrar en el grupo...

esto debería funcionar, como se esperaba

 import Foundation let s = DispatchSemaphore(value: 1) let dg = DispatchGroup() func go() -> Void { for i in 1...2 { doWork(attemptNo: i, who: "Lily", secs: Double.random(in: 1.0...5.0)) doWork(attemptNo: i, who: "Emmie", secs: Double.random(in: 1.0...10.0)) doWork(attemptNo: i, who: "Wiley", secs: Double.random(in: 1.0...3.0)) } } func doWork(attemptNo: Int, who: String, secs: TimeInterval) -> Void { dg.enter() DispatchQueue.global().async { //dg.enter() print("\(who) wants to work, will wait \(secs) seconds, attempt #\(attemptNo)") if s.wait(timeout: .now() + secs) == .timedOut { print("\(who) was denied. No soup for me! Task #\(attemptNo) not going to happen.") dg.leave() return } let workSecs = UInt32(Int.random(in: 1...3)) print("\(who) went to work for \(workSecs) seconds on task #\(attemptNo)") sleep(workSecs) print("\(who) is sliding down the dinosaur tail. Task #\(attemptNo) all done!") s.signal() dg.leave() } } go() dg.notify(queue: .global(), execute: {print("Everyone is done.")})

La mejor manera de evitar tal error es usar la API adecuada

 func doWork(attemptNo: Int, who: String, secs: TimeInterval) -> Void { DispatchQueue.global().async(group: dg) { print("\(who) wants to work, will wait \(secs) seconds, attempt #\(attemptNo)") if s.wait(timeout: .now() + secs) == .timedOut { print("\(who) was denied. No soup for me! Task #\(attemptNo) not going to happen.") return } let workSecs = UInt32(Int.random(in: 1...3)) print("\(who) went to work for \(workSecs) seconds on task #\(attemptNo)") sleep(workSecs) print("\(who) is sliding down the dinosaur tail. Task #\(attemptNo) all done!") s.signal() } }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda