14

This code

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
      NSLog(@"Main Thread? %d", [NSThread isMainThread]);
});

shows that I'm in the main thread. Even doing this:

queue = dispatch_queue_create("nonMainQueue", NULL);

still reports that I'm in the main queue. This is, it seems, because I'm using dispatch sync.

Does this mean that my code is the same as not using dispatch_sync at all? Also: what's the point of dispatch_sync if it does nothing at all, then?

Community
  • 1
  • 1
Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
  • 9
    Queues != Threads. – Richard J. Ross III Feb 05 '13 at 20:33
  • @RichardJ.RossIII that's the issue. I'm actually seeing (or imagining) an increase in performance using dispatch_sync. Am I out of my mind (since `isMainThread` returns YES in all cases)? – Dan Rosenstark Feb 05 '13 at 20:35
  • try using `dispatch_get_current_queue() == dispatch_get_main_queue()` instead. You are not out of your mind, I promise :) – Richard J. Ross III Feb 05 '13 at 20:37
  • Thanks Rob, I would try that if I wanted async. Thanks @RichardJ.RossIII, that's awesome. ` assert(dispatch_get_current_queue() != dispatch_get_main_queue() && "this better not be main");` – Dan Rosenstark Feb 05 '13 at 20:47
  • @RichardJ.RossIII would you be so kind as to make that an answer, since you've found the hole in my knowledge? Thanks! – Dan Rosenstark Feb 05 '13 at 20:48
  • `dispatch_get_current_queue` is deprecated. Fine for diagnostic purposes, but I wouldn't go putting that in production code. – Rob Feb 05 '13 at 20:49
  • Thanks Rob, is there a non-deprecated way to check? I'll remove it anyway, but developers do forget. – Dan Rosenstark Feb 05 '13 at 20:49
  • 1
    [here](https://devforums.apple.com/message/710745) you have thread in apple dev forums where guys from apple are describing why it is deprecated and how to deal with it – lupatus Feb 05 '13 at 21:23
  • @Yar BTW, you ask, "Does this mean that my code is the same as not using `dispatch_sync` at all? Also: what's the point of `dispatch_sync` if it does nothing at all, then?" IMHO, there is no point in `dispatch_sync` to a global queue. Async, sure, but not sync. The benefit of `dispatch_sync` is exhibited when dispatching to your own serial queue which is managing some shared resource. `dispatch_sync` is invaluable tool in this scenario (but probably few others). – Rob Feb 06 '13 at 21:56
  • @Rob, I'm finding that, though it's executing on the same thread, it's actually MUCH faster (no real measurements of that). Am I hallucinating? [feel free to say yes] If I make the code async, then everything gets out of order and I'd need to find another solution. – Dan Rosenstark Feb 07 '13 at 01:37
  • I've broken this out to a separate q: http://stackoverflow.com/questions/14742184 – Dan Rosenstark Feb 07 '13 at 01:46

3 Answers3

11

Because queues are not threads, in order to check if you are on the main 'queue', you must use different code, something similar to this:

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
   NSLog(@"On Main Thread!");
}

Just note that dispatch_get_current_queue is deprecated, and is subject to be completely removed in a later iOS/Mac OS version.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • that's amazing, thanks for seeing my error. Sometimes the OP doesn't have a clue ;) Any non-deprecated options for `dispatch_get_current_queue`? – Dan Rosenstark Feb 05 '13 at 20:53
  • @Yar unfortunately not. I don't expect it to be going anywhere soon, but you never know when apple will just remove it from the APIs entirely. If that's a huge deal to you, then I would consider filing a bug report with apple requesting it's presence throughout later versions of iOS. – Richard J. Ross III Feb 05 '13 at 20:55
  • @Rob read again, [here](https://developer.apple.com/library/mac/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_get_current_queue): `When called from outside of the context of a submitted block, this function returns the main queue if the call is executed from the main thread. If the call is made from any other thread, this function returns the default concurrent queue.` – Richard J. Ross III Feb 05 '13 at 21:01
  • Your comment was in response to my observation that the header file says "When dispatch_get_current_queue() is called on the main thread, it may or may not return the same value as dispatch_get_main_queue(). Comparing the two is not a valid way to test whether code is executing on the main thread." Your code sample seems to be suggesting that if they're the same, you should report "On Main Thread!" – Rob Feb 05 '13 at 21:10
  • @Rob that does not exist in the documentation, only in the header files, which may be outdated. When in doubt, I go with the official apple docs and man pages, which specifically state that it *will* return the main queue. – Richard J. Ross III Feb 05 '13 at 21:13
  • 2
    Fair enough. I personally wouldn't rely on a function listed at deprecated in 6.0 with an explicit admonition that it shouldn't be used in the manner you suggest. And given that the docs failure to acknowledge that it's deprecated doesn't instill confidence there, either. Hey, if it works for you, run with it. I just don't share your confidence in the documentation. – Rob Feb 05 '13 at 21:24
  • @RichardJ.RossIII Please have a look at this http://stackoverflow.com/questions/13972048/dispatch-sync-always-scheduling-a-block-on-main-thread. I believe apple docs are contradicting or am I missing something. – Evol Gate Feb 06 '13 at 03:46
5

This is documented behavior. As an optimization the blocks passed to dispatch_sync are executed on the current thread if possible (which is almost always).

Sven
  • 22,475
  • 4
  • 52
  • 71
  • Please have a look at this http://stackoverflow.com/questions/13972048/dispatch-sync-always-scheduling-a-block-on-main-thread. I believe apple docs are contradicting or am I missing something. – Evol Gate Feb 06 '13 at 03:44
  • But if they are executed on the current thread, is the speed of the operation identical to not using `dispatch_sync` at all? – Dan Rosenstark Feb 06 '13 at 06:31
  • 2
    dispatch_sync against a global concurrent queue is a noop, it executes the specified block directly. This is because the global concurrent queues have no ordering. – das Feb 06 '13 at 06:53
1

My understanding from Apple's GCD guide, there is no guarantee that dispatch queues will execute on a separate thread. GCD will determine which thread, and if necessary create a new one.

Part of the point is now you do not have to think about threads.

The only thing to keep in mind, is to make sure you are updating UI elements on the main queue, for example:

// on background queue
dispatch_async( dispatch_get_main_queue(), ^(void){
    someLabel.text = @"My Text";
});
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
Mike D
  • 4,938
  • 6
  • 43
  • 99