0

In my app I use the following method to check for values of certain variables which are meant to be accessed on the main thread only.

Now that I began to implement APNs and when my app is woken by APNs it seems that code execution (in background) is always stuck at the point indicated using comments:

- (void) xttSyncOnMainThread:(void (^)(void))prmBlock {
    if (![NSThread isMainThread]) {
        dispatch_queue_t mtQueue = dispatch_get_main_queue(); // will be executed
        // execution is stuck here
        dispatch_sync(mtQueue, prmBlock); // won't be executed
    } else {
        prmBlock();
    }
}

Do I need to move all code to non-MT queues or am I missing something else?

Thanks a lot!

McMini
  • 305
  • 3
  • 15

4 Answers4

0

Because dispatch_sync on main queue cause deadlock.

More information about dispatch_sync and main queue is for example here:

dispatch_sync on main queue hangs in unit test

Why dispatch_sync( ) call on main queue is blocking the main queue?

Can you just use dispatch_async method ?

Jakub Průša
  • 2,255
  • 1
  • 14
  • 19
  • How do you think this causes a deadlock? If I am not in background but instead my app is in 'active mode' it works perfectly. I even check if the current thread is the main thread to avoid a deadlock. – McMini Jul 14 '17 at 10:16
  • I my opinion doesn't matter from which thread you run dispatch_sync on main queue. Because main queue waiting for everything is complete before start your block. But this never happen because your block is in queue and waiting to be dispatched. You block yourself. Maybe my description isn't best but this is basically what is written in related issues. – Jakub Průša Jul 14 '17 at 11:55
  • I'm not sure how much you need sync call. But I would try to simplify your method to only run on main thread by async call. dispatch_async(dispatch_get_main_queue(), ^{ prmBlock() } – Jakub Průša Jul 14 '17 at 11:57
0

why are you passing prmBlock to dispatch_sync

usually it is like

dispatch_sync(dispatch_get_main_queue(), ^(void) {
        // write the code that is to be executed on main thread
});

But if you use disptch_sync it will wait for the block to complete execution and then return. If you don't want to block the execution use

dispatch_async(dispatch_get_main_queue(), ^(void) {
        // write the code that is to be executed on main thread
});
hariszaman
  • 8,202
  • 2
  • 40
  • 59
  • I use a method with a parameter to avoid duplicating the code for checking if I am already in the main thread. – McMini Jul 14 '17 at 10:18
  • I don't understand your question what do you want to do on main thread? please clear your question. whatever you want to do on main thread so be under ^(void) { // write the code that is to be executed on main thread }. If you are just passing the prmBlock to queue where will it be executed or do you even want to do anything in that case with prmBlock? – hariszaman Jul 14 '17 at 12:34
0

Ok, after some more testing I found that in my case (while the code in the question works just fine) the problem came from accidently calling the completionhandler from the APNs delegate too soon.

McMini
  • 305
  • 3
  • 15
-1
 - (void) xttSyncOnMainThread:(void (^)(void))prmBlock {

    dispatch_async(dispatch_get_main_queue(), ^{
    //code here to perform
    }); 
 }
张冬冬
  • 1
  • 2