Evgeniy Kleban
Evgeniy Kleban

Reputation: 6965

dispatch_sync not working with main queue

please consider following code:

dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_t myGroup = dispatch_group_create();

    dispatch_group_async(myGroup, myQueue, ^{
        NSLog(@"First block of code");
    });

    dispatch_group_async(myGroup, myQueue, ^{
        NSLog(@"Second block of code");
    });

    dispatch_group_async(myGroup, myQueue, ^{


        dispatch_sync(dispatch_get_main_queue(), ^{ //problem here

            dispatch_time_t myTime = dispatch_time(DISPATCH_TIME_NOW, 10ull * NSEC_PER_SEC);

            dispatch_after(myTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSLog(@"Third block of code work");

            });
        });

    });

    dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
    NSLog(@" All done ?");

Problem is in dispatch_sync(dispatch_get_main_queue(), ^{ When i make dispatch_async(dispatch_get_main_queue(), ^{, it works as it should. Point of making that sync, is blocking main thread for 10 seconds, simulating "hard work". But, unfortunately, its not work. I wonder why?

What i want is: dispatch_sync block main thread for only 10 seconds, then execution continues.

What in fact happening: dispatch sync block whole application from any further execution.

Upvotes: 1

Views: 939

Answers (2)

gnasher729
gnasher729

Reputation: 52622

Your code is presumably run on the main queue. It dispatches three blocks on the background, then waits until all three blocks have finished running. Since this is done on the main queue, other blocks will only start running on the main queue afterwards, that is after all the three async blocks that you queued up have finished.

Now the third of these three blocks calls the main thread with a sync call. What that means is it adds a block to the main queue, then it waits until the block starts executing, then it waits further until the block finishes executing, then the dispatch_sync call returns to its caller.

Well, that block dispatched to the main thread cannot start executing, because the main thread is busy waiting for the three async blocks to finish, and one of them won't finish because it is waiting for the block dispatched to the main thread to start executing, which it can't because and so on and so on forever. It doesn't actually matter one bit what you are trying to do in the synchronous block, because that block never gets as far as starting to execute.

Upvotes: 2

bbum
bbum

Reputation: 162722

If that code is running on the main event loop, then the dispatch_group_wait() is going to block the main queue. That prevents the synchronous execution of any block on the main queue and leads to deadlock.

You can verify this by pausing into the debugger. You'll likely see the main thread/queue blocked on the call to wait and a secondary thread/queue blocked on dispatch_sync.

Upvotes: 3

Related Questions