8

Apparently I can only use DispatchSemaphore if I deal with different queues. But what if I want to run async code on the same queue (in this case the main queue).

let s = DispatchSemaphore(value : 0)
DispatchQueue.main.async {
   s.signal()
}
s.wait()

This snippet doesn't work, because the async code is also waiting, because the semaphore blocked the main queue. Can I do this with semaphore? Or do I need to run the async code on a different queue?

ps. I know I could use sync, instead of async and semaphore in this snippet. But This is just an example code to reproduce an async call.

aneuryzm
  • 63,052
  • 100
  • 273
  • 488
  • 1
    The whole point of `DispatchSemaphore` is to control access to a resource across multiple threads. It makes no sense to use it with a single thread. – ian Aug 28 '19 at 14:20
  • 1
    @ian If I call async, don't I run that code on a different thread? – aneuryzm Aug 28 '19 at 15:44

2 Answers2

4

All of this in on the main thread, so the semaphore.signal() will never be called because the thread will stop on the semaphore.wait() and not continue on.

If you are trying to run some async code and have the main thread wait for it, run that code on a different queue and have it signal the semaphore when it's done, allowing the main thread to continue.

dktaylor
  • 874
  • 7
  • 12
  • However, when i call async (even if it's the same queue, in this case the main queue), don't I run the code on a different thread? Why the async code is blocked, if I call wait on the main thread? – aneuryzm Aug 28 '19 at 15:58
  • Calling async on the main queue will still be on the main thread, it just won’t be executed immediately – dktaylor Aug 28 '19 at 15:59
  • I see, so I guess there is no time to run the thread code in async, even if async is called before wait... ? – aneuryzm Aug 28 '19 at 16:01
  • 1
    Yep, the queue has not gotten to the async code block before the wait is called – dktaylor Aug 28 '19 at 16:02
  • After 2 years, this comment helped me so much! Thank you both :) – aliyasineser Jul 05 '22 at 07:19
-1

what if I want to run async code on the same queue (in this case the main queue).

Then use DispatchGroup instead. That is not what DispatchSemaphore is for.

Run this code in a playground.

import Foundation

let d = DispatchGroup()
var v:Int = 1
d.enter()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    v = 7
    d.leave()
}

d.notify(queue: DispatchQueue.main) {
    print("v = \(v)")
}

The output will be v = 7. If you comment out d.enter() and d.leave() then the output will be v = 1.

If I call async, don't I run that code on a different thread?

No, you need to understand thread run loops in general and iOS's Main Event Loop specifically.

Jeff
  • 3,829
  • 1
  • 31
  • 49
  • Thanks. No offence, but I think you need to understand the questions and read the answers. 1) The question was already answered correctly and solved time ago. 2) I know there is DispatchGroup, but my question was about DispatchSemaphore to better understand this object. 3) The reason why your snippet works is that you can use notify() with dispatchGroup. If you called dispatchGroup.wait() you would have the same problem. – aneuryzm Sep 04 '19 at 06:59
  • 4) Regarding the question "If I call async, don't I run that code on a different thread?", again this has already been answered, so no need to write "you need to understand..." cheers – aneuryzm Sep 04 '19 at 06:59
  • @aneuryzm The question and answer is not just for you, but for others that come after. To "run async code on the same queue" one should use DispatchGroup not DispatchSemaphore. This question is an X,Y question. Stopping the main thread is most times a bug. – Jeff Sep 04 '19 at 19:07
  • @aneuryzm about "need to understand", all your questions indicated fundamental ignorance of run loops and threading. I provided doc link to run loops to be helpful because those docs are hard to find. And your comment above about `dispatchGroup.wait` indicates you still do not understand. – Jeff Sep 04 '19 at 19:21
  • Your answer and these last comments definitely indicate a conceited attitude. The question was already answered in the question comments and in the original accepted answer. The additional (not strictly required) information that you provide (DispatchGroup) is incomplete: what about DispatchWorkItem as possible solution then? The link to "docs are hard to find" are actually easy to find: just google "Apple threads" and you'll see the result in the second position. Finally, I welcome your opinion about my "fundamental ignorance" on the topic, always useful to get some feedback. – aneuryzm Sep 06 '19 at 12:24