Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a scenario in my app, where I want to do some time consuming task which consists of some data processing as well as UI update, in a method. My method looks like this,

- (void)doCalculationsAndUpdateUIs {      // DATA PROCESSING 1     // UI UPDATE 1      // DATA PROCESSING 2     // UI UPDATE 2      // DATA PROCESSING 3     // UI UPDATE 3 }  

As it is time consuming I wanted to do the data processing on the background thread, using,

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{ 

But as both data processing and UI updates are in the same method, I wanted to move only the UI updates in main thread using,

dispatch_async(dispatch_get_main_queue(), ^{ 

Finally my method looks like this,

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

Does this really work? Is this really a good practice? What is the best way to achieve this?

P.S. All these three operations are interrelated to each other.


EDIT: Sorry guys. I have missed a line in the above code. My actual code looks like this.

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

Once again, I really apologize for the confusion.

like image 673
EmptyStack Avatar asked Jul 05 '13 13:07

EmptyStack


2 Answers

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 finish dispatch_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.

like image 153
David Rönnqvist Avatar answered Sep 28 '22 10:09

David Rönnqvist


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.

like image 44
StatusReport Avatar answered Sep 28 '22 10:09

StatusReport