1

I'm having some issues using dispatch_async. On my applications main/UI thread, I call dispatch_async on the global queue, and tell it to go do some function call which has a completion handler. I'm expecting the completion handler to get called but it does not appear to sometimes.

dispatch_queue_t hiq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_async(hiq, ^(void){
            [object doSomethingAndThenCompletionHandler:^(){
                //Do some stuff because I'm done
            }];
        });

What is interesting is, I'm doing this in response to a controlTextDidChange whenever I type something into a textfield. When I click out of the textfield, all of the completion handlers fire at once.

My guess is that all of my completion handlers are getting queued up behind something on the run loop and then when my UI element loses focus, that frees up the queue. I'm not enough of an expert on run loops to know what exactly is happening as I'm typing in a textfield or combobox but perhaps it's tying up the runloop?

EDIT: I think it has to do with the run loop mode because when I print out the run loop mode it prints out as NULL except for in the completion handler when it prints out as the default mode. I'm using a combo box and the issue is only present when the combobox is open and expanded. UIScrollView blocks run loop? I think it might have to do with this issue. What do you guys think?

Community
  • 1
  • 1
JPC
  • 8,096
  • 22
  • 77
  • 110
  • 1
    You do not have to muck around with the run loop to get `dispatch_async` to work. What are you doing in your completion handler? – Rob Keniger Jan 07 '12 at 22:06
  • Right now it's just some print statements to test if it works. I've also noticed that it seems to be affected by other UI triggers. If I type a character or two in the textfield, and then click out of the textfield so it loses focus, all of my completion handlers fire – JPC Jan 07 '12 at 22:09
  • I'm not trying to accomplish anything. It wasn't working without it so I put it in to see if that would make it work. It's really just there for experimentation – JPC Jan 07 '12 at 22:18
  • Just did a quick test, and I'm not seeing the results you describe; `controlTextDidChange:`, `doSomethingAndThenCompletionHandler:` (just a log and then a call to the handler), and the handler itself all run immediately. It's pretty much impossible to help you without seeing `doSomething...` – jscs Jan 07 '12 at 23:42
  • Hey Josh, I made some edits. It's only with a combo box being open and expanded that this happens – JPC Jan 07 '12 at 23:48
  • How are you printing the run loop mode, and which run loop's mode are you printing? – Peter Hosey Jan 08 '12 at 01:43
  • Sounds like maybe the combo box is entering a [Private Tracking Loop](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html%23//apple_ref/doc/uid/10000060i-CH6-SW4) and snarfing up all events while its menu is displayed. – jscs Jan 09 '12 at 19:44

2 Answers2

1

When you do [[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow], it enters the run loop recursively, and the run loop processes events normally. So it will call your method again if the text field receives another event. The stack trace would look something like this (with lots more frames related to NSRunLoop):

main
NSApplicationMain
-[NSRunLoop runUntilDate:]
your method
-[NSRunLoop runUntilDate:]
your method

I have no idea why you're calling runUntilDate:, but it's probably not for a good reason.

If you want help understanding why your completion handler isn't getting called, then you need to show us the definition of your doSomethingAndThenCompletionHandler: method.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • I updated my post to better reflect the issue. I'm not using the run loop stuff – JPC Jan 07 '12 at 22:21
  • 1
    We still need to see the definition of `doSomethingAndThenCompletionHandler:`. – rob mayoff Jan 07 '12 at 22:29
  • Unfortunately I can't show the definition but I can say that it makes some asynchronous requests using nsurlconnection...the requests all work too, my completion handlers just don't get called back until my UI element loses focus – JPC Jan 07 '12 at 22:37
  • 1
    Without being able to see the implementation of doSomethingAndThenCompletionHandler: I'm afraid it's impossible to say for sure what's going on... – Andrew Madsen Jan 07 '12 at 22:56
  • Hmm, well it was worth a shot. My guess is that all of my completion handlers are getting queued up behind something on the run loop and then when my UI element loses focus, that frees up the queue. I'm not enough of an expert on run loops to know what exactly is happening as I'm typing in a textfield or combobox but perhaps it's tying up the runloop? – JPC Jan 07 '12 at 23:06
  • 1
    You're going to need to show us *some* code that we can use to reproduce the issue and assist you. It's not possible to reproduce the problem otherwise, because something is happening in your `doSomethingAndThenCompletionHandler:` code that is causing this problem. – Rob Keniger Jan 07 '12 at 23:10
  • 1
    Put a breakpoint in your text field event handler method. Look at the stack trace. If it looks like NSRunLoop (or CFRunLoop) has been entered recursively, then maybe NSTextField runs the runloop in a private mode that doesn't drain the GCD dispatch queue containing your completion handlers. – rob mayoff Jan 07 '12 at 23:11
  • 1
    I should add that I think it's very unlikely that NSTextField does what I described. – rob mayoff Jan 07 '12 at 23:12
  • Nothing that looks like it's coming from another run loop but thanks for the suggestion. – JPC Jan 07 '12 at 23:17
  • Could it have to do with the run loop mode? – JPC Jan 07 '12 at 23:28
0

Figured out the issue I think. Some of the libraries I'm using are most likely sending NSURLConnections out without scheduling to run in common run loop modes. When the combo box is open the run loop mode changes to event tracking mode and then can't get call backs for them.

JPC
  • 8,096
  • 22
  • 77
  • 110