Boon
Boon

Reputation: 41510

dispatch_async call into dispatch_async vs dispatch_async call into dispatch_sync

I have seen common idioms of dispatch_async calling into dispatch_async vs dispatch_async calling into dispatch_sync.

In some circumstances, the latter can be substituted with the former. Question is, in what situation can you only use one and not the other?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    dispatch_async(dispatch_get_main_queue(), ^{
       //
    });
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    dispatch_sync(dispatch_get_main_queue(), ^{
       //
    });
});

Upvotes: 1

Views: 211

Answers (2)

Ken Thomases
Ken Thomases

Reputation: 90681

I would say that you should strive to avoid blocking threads. If you're tempted to use dispatch_sync() because there's code to run after the stuff you're shunting to the main thread completes, you should instead use "continuation passing" coding style. The task you submit to the main queue should submit a new task to a concurrent queue. So, the code might look like:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // A) Some code here

    dispatch_async(dispatch_get_main_queue(), ^{
        // B) some code here

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // C) Some code here
        });
    });
});

The main reason to use dispatch_sync() is when you're implementing an inherently synchronous interface but you need to dispatch a task to a queue to accomplish that. That usually only happens when you're using a serial dispatch queue (or barrier tasks on a concurrent queue) to protect a shared resource.

Given that the original code already has a dispatch_async() call, it can't be implementing a synchronous interface.

Upvotes: 1

rmaddy
rmaddy

Reputation: 318944

The 2nd option only makes sense if you have other code inside the dispatch_async and you want that code executed after the code inside dispatch_sync completes.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // A) Some code here

    dispatch_sync(dispatch_get_main_queue(), ^{
       // B) some code here
    });

    // C) Some code here
});

This ensures A is executed, then B (on the main thread), then C (on the background thread but after the B code is done).

If there is no C code, using dispatch_sync or dispatch_async for the inner dispatch result in the same thing.

Upvotes: 1

Related Questions