On Sep 5, 2014, at 1:44 PM, Jonathan Guy <jonathan...@mac.com> wrote:

> This is for MacOS not iOS.
> 
> If your running code on a GCD queue
> 
> dispatch_sync(dispatch_get_main_queue(), ^{
>   //do UI stuff
> });
> 
> is pretty much the way to do UI stuff on the main thread/queue which seems to 
> work well for iOS. MacOS seems to be a different story. Try this for a simple 
> example
> 
> - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
> {
>   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
> 0), ^{
> 
>       // So my app is doing some background stuff
>       // and I need a file from the user so
> 
>       // code blah blah code
> 
>       dispatch_sync(dispatch_get_main_queue(), ^{
>           NSOpenPanel *op = [NSOpenPanel openPanel];
> 
>           [op runModal];
>       });
> 
>       // resume code blah blah code
>   });
> }
> when the NSOpenPanel opens all kinds of weirdness is going on. The scroll 
> views scroll very erratically if at all and the directories don't list 
> properly. I'm just using the NSOpenPanel here as an example, this also 
> happens with any view that contains a scroll view (so I've tested so far). Is 
> this a bug? Are others seeing this or is it just me and is there another 
> preferred way of doing this?

This is an issue I have encountered before.  NSOpenPanel does certain 
operations, like loading the icons for files, asynchronously in the background. 
 Then, when those background operations are completed, it updates the dialog by 
submitting tasks to the main dispatch queue.  However, the main dispatch queue 
is a serial queue.  It is currently monopolized by your block which has called 
into -runModal.  It won't execute any more tasks until that block completes.  
So, the panel's asynchronous background work can't complete.

It doesn't matter whether your block was submitted to the main queue with 
dispatch_sync() or dispatch_async().  I agree with others that, in general, you 
should structure your code to submit blocks asynchronously whenever possible 
(regardless of which queue you're submitting them to).  Similarly, you should 
avoid blocking whenever possible, preferring asynchronous, callback-based APIs. 
 However, none of that affects this issue.

It's simply the case that NSOpenPanel can't be run, directly or indirectly, 
from a block submitted to the main dispatch queue.

You can use -performSelectorOnMainThread:… just fine.  That is not a serialized 
mechanism.  If the run loop is in the middle of performing a selector and is 
re-entered (as for the modal event loop run for a modal dialog), it can still 
run other submitted dispatch tasks and performed selectors.

Because of this, I consider it a bug that NSOpenPanel uses GCD rather than 
-performSelectorOnMainThread:… or a similar non-serial mechanism for getting 
its updates back to the main thread.  And everybody else using GCD should 
carefully consider this issue in their own designs.  (Note that it also doesn't 
matter whether NSOpenPanel has submitted its updates from the background to the 
main thread synchronously or asynchronously.  If it submits it asynchronously, 
the background thread can continue, but it will just have an opportunity to 
queue more things on the main queue that will never get run.  If it submits 
synchronously, it will block, but that's just as well.)

Frankly, Apple should add a new dispatch queue that is serviced by the main 
thread but which is technically not a serial queue.  It won't be quite a fully 
concurrent queue, since it would only be serviced by one thread, but it would 
allow blocks to be serviced in a nested fashion if one of those blocks runs the 
run loop.  Basically, it would work just like -performSelectorOnMainThread:… 
does.

Regards,
Ken


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to