dispatch_async block on main queue is never execeuted

浪尽此生 提交于 2019-12-21 03:25:09

问题


I have an app that uses a connection queue that handles the connections on a background thread. Each connection sends a JSON post, then when it receives a success, saves some objects into coredata.

Once all connections are complete, i call a dispatch_async on the main thread to call a finished method.

However, under very specific conditions of data im sending/saving, I've noticed the dispatch_async block to the main thread never gets called, and the app screen freezes, all execution stops, and the app sits idle with a frozen screen. processing power according to xcode is 0%.

Here is method with the block that fails.

- (void)connectionDidComplete
{
    _completeConnections++;

    _syncProgress = (float)_completeConnections / (float)_totalConnections;

    dispatch_async(mainQueue, ^(void) {
        [[NSNotificationCenter defaultCenter] postNotificationName:SyncQueueDidUpdateNotification object:nil];
    }); <-- this dispatch works

    if (_completeConnections == _totalConnections)
    {
        // clear unsynced data
        NSArray *syncedObjects = [SyncObject completedSyncObjects];

        if (syncedObjects.count > 0)
        {
            for (SyncObject *syncObject in syncedObjects)
            {
                [syncObject delete];
            }
        }

        //this method saves the current context, then merges this context with the main context right after
        [[VS_CoreDataManager sharedManager] saveManagedObjectContextAndWait:managedObjectContext];

        // cleanup the thread's context
        [[VS_CoreDataManager sharedManager] unRegisterManagedObjectContextForThread:currentThread];
        managedObjectContext = nil;

        // complete sync
        dispatch_async(mainQueue, ^(void) {
            [self performSelector:@selector(finishSync) withObject:nil afterDelay:2];
        }); <-- this dispatch never gets called
    }
}

My suspicion is this problem has something to do with saving the context then merging it. And possibly while that is happening its released in the middle of the merge, causing some weird hang up and the dispatch isn't getting executed. This is just a guess though, and I don't know how to fix it.

Any ideas?

Thanks.


回答1:


If the block on the main thread is not executed, then it is because of 1 of 2 reasons.

  1. The main thread is blocked; is not processing any events at all. Got a while() loop on the main thread? That'd do it. A lock? There you go.

  2. The main thread is running a modal run loop inside the outer run loop. Asynchronous dispatches to the main event loop -- main thread -- won't be processed in this case.

Set a breakpoint on that dispatch_async() and see what the main thread is doing (at the point of dispatch the main thread is most likely already in the bad state).

DarkDust's suggestion of using dispatch_after() is a good one, but is unlikely to work in that it is almost assuredly the case that your main thread is not processing events when the problem occurs. I.e. fix the problem, then move to dispatch_after() as DarkDust suggests.




回答2:


I believe this is a great discussion. I came across this when I had the following code:

   dispatch_synch(dispatch_get_main_queue()){
        print("I am here")
   }

the print code did not execute as I was dispatching a 'synch' block on the serial main thread which caused a dead lock. print was waiting for the dispatch to finish and dispatch was waiting for print to finish. When you dispatch in the main serial queue then you should use dispatch_async. and i guess if you use a concurrent queue then dispatch synch suits better




回答3:


If your main thread is busy with modal runloop, then you could try

CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, block
    });


来源:https://stackoverflow.com/questions/21120035/dispatch-async-block-on-main-queue-is-never-execeuted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!