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

时间:2022-11-18 19:32:15

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.

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

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

一旦所有连接完成,我在主线程上调用dispatch_async来调用已完成的方法。

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%.

但是,在非常特定的数据发送/保存条件下,我注意到主线程的dispatch_async块永远不会被调用,应用程序屏幕冻结,所有执行停止,应用程序处于空闲状态并冻结屏幕。根据xcode的处理能力为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.

谢谢。

3 个解决方案

#1


21  

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

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

  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.

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

  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).

在dispatch_async()上设置一个断点,看看主线程正在做什么(在调度点,主线程很可能已经处于坏状态)。

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.

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

#2


0  

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

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

#3


-1  

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

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

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

#1


21  

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

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

  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.

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

  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).

在dispatch_async()上设置一个断点,看看主线程正在做什么(在调度点,主线程很可能已经处于坏状态)。

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.

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

#2


0  

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

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

#3


-1  

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

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

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