主队列上的dispatch_async块永远不会被占用

时间:2014-01-14 17:31:25

标签: ios objective-c xcode multithreading grand-central-dispatch

我有一个应用程序,它使用连接队列来处理后台线程上的连接。每个连接发送一个JSON帖子,然后当它收到成功时,将一些对象保存到coredata中。

所有连接完成后,我在主线程上调用dispatch_async来调用finished方法。

但是,在非常具体的数据发送/保存条件下,我注意到主线程的dispatch_async块永远不会被调用,应用程序屏幕冻结,所有执行停止,应用程序处于空闲状态用冷冻的屏幕。根据xcode的处理能力为0%。

这是块失败的方法。

- (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
    }
}

我怀疑这个问题与保存上下文然后合并它有关。并且可能正在发生它在合并过程中发布,导致一些奇怪的挂断并且调度没有被执行。这只是一个猜测,我不知道如何解决它。

有什么想法吗?

感谢。

3 个答案:

答案 0 :(得分:23)

如果主线程上的块没有被执行,则是由于2个原因之一。

  1. 主线被阻止;根本不处理任何事件。在主线程上有一个while()循环?那就做了。锁?你去吧。

  2. 主线程在外部运行循环内运行模态运行循环。主要事件循环的异步调度 - 主线程 - 在这种情况下不会被处理。

  3. dispatch_async()上设置一个断点,看看主线程在做什么(在发送时,主线程很可能已经处于坏状态)。

    DarkDust使用dispatch_after()的建议是一个很好的建议,但不太可能有效,因为几乎可以确定你的主线程在问题发生时没有处理事件。即解决问题,然后按照DarkDust的建议移至dispatch_after()

答案 1 :(得分:0)

我相信这是一次很棒的讨论。当我有以下代码时,我遇到了这个:

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

打印代码没有执行,因为我在串行主线程上调度了一个导致死锁的'synch'块。打印等待发送完成,发送等待打印完成。当您在主串行队列中调度时,您应该使用dispatch_async。我想如果你使用并发队列,那么调度同步更适合

答案 2 :(得分:-1)

如果您的主线程忙于模态运行循环,那么您可以尝试

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