Does dispatch_async(dispatch_get_main_queue(), ^{...}); wait until done? Does dispatch_async(dispatch_get_main_queue(), ^{...}); wait until done? multithreading multithreading

Does dispatch_async(dispatch_get_main_queue(), ^{...}); wait until done?


No it doesn't wait and the way you are doing it in that sample is not good practice.

dispatch_async is always asynchronous. It's just that you are enqueueing all the UI blocks to the same queue so the different blocks will run in sequence but parallel with your data processing code.

If you want the update to wait you can use dispatch_sync instead.

// This will wait to finishdispatch_sync(dispatch_get_main_queue(), ^{    // Update the UI on the main thread.});

Another approach would be to nest enqueueing the block. I wouldn't recommend it for multiple levels though.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    // Background work    dispatch_async(dispatch_get_main_queue(), ^{        // Update UI        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{            // Background work            dispatch_async(dispatch_get_main_queue(), ^{                // Update UI            });        });    });});

If you need the UI updated to wait then you should use the synchronous versions. It's quite okay to have a background thread wait for the main thread. UI updates should be very quick.


You have to put your main queue dispatching in the block that runs the computation. For example (here I create a dispatch queue and don't use a global one):

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);dispatch_async(queue, ^{  // Do some computation here.  // Update UI after computation.  dispatch_async(dispatch_get_main_queue(), ^{    // Update the UI on the main thread.  });});

Of course, if you create a queue don't forget to dispatch_release if you're targeting an iOS version before 6.0.


Your proposed doCalculationsAndUpdateUIs does data processing and dispatches UI updates to the main queue. I presume that you have dispatched doCalculationsAndUpdateUIs to a background queue when you first called it.

While technically fine, that's a little fragile, contingent upon your remembering to dispatch it to the background every time you call it: I would, instead, suggest that you do your dispatch to the background and dispatch back to the main queue from within the same method, as it makes the logic unambiguous and more robust, etc.

Thus it might look like:

- (void)doCalculationsAndUpdateUIs {    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{        // DATA PROCESSING 1         dispatch_async(dispatch_get_main_queue(), ^{            // UI UPDATION 1        });        /* I expect the control to come here after UI UPDATION 1 */        // DATA PROCESSING 2        dispatch_async(dispatch_get_main_queue(), ^{            // UI UPDATION 2        });        /* I expect the control to come here after UI UPDATION 2 */        // DATA PROCESSING 3        dispatch_async(dispatch_get_main_queue(), ^{            // UI UPDATION 3        });    });}

In terms of whether you dispatch your UI updates asynchronously with dispatch_async (where the background process will not wait for the UI update) or synchronously with dispatch_sync (where it will wait for the UI update), the question is why would you want to do it synchronously: Do you really want to slow down the background process as it waits for the UI update, or would you like the background process to carry on while the UI update takes place.

Generally you would dispatch the UI update asynchronously with dispatch_async as you've used in your original question. Yes, there certainly are special circumstances where you need to dispatch code synchronously (e.g. you're synchronizing the updates to some class property by performing all updates to it on the main queue), but more often than not, you just dispatch the UI update asynchronously and carry on. Dispatching code synchronously can cause problems (e.g. deadlocks) if done sloppily, so my general counsel is that you should probably only dispatch UI updates synchronously if there is some compelling need to do so, otherwise you should design your solution so you can dispatch them asynchronously.


In answer to your question as to whether this is the "best way to achieve this", it's hard for us to say without knowing more about the business problem being solved. For example, if you might be calling this doCalculationsAndUpdateUIs multiple times, I might be inclined to use my own serial queue rather than a concurrent global queue, in order to ensure that these don't step over each other. Or if you might need the ability to cancel this doCalculationsAndUpdateUIs when the user dismisses the scene or calls the method again, then I might be inclined to use a operation queue which offers cancelation capabilities. It depends entirely upon what you're trying to achieve.

But, in general, the pattern of asynchronously dispatching a complicated task to a background queue and then asynchronously dispatching the UI update back to the main queue is very common.