xcode 主队列上的 dispatch_async 块永远不会被执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21120035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dispatch_async block on main queue is never execeuted
提问by JMD
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 post,然后当它收到成功时,将一些对象保存到 coredata 中。
Once all connections are complete, i call a dispatch_async
on the main thread to call a finished
method.
一旦所有连接都完成,我dispatch_async
在主线程上调用 a 来调用一个finished
方法。
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.
谢谢。
回答by bbum
If the block on the main thread is not executed, then it is because of 1 of 2 reasons.
如果主线程上的块没有执行,那么是因为 2 个原因之一。
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.
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.
主线程被阻塞;根本不处理任何事件。在主线程上有一个 while() 循环?就可以了。一把锁?你去吧。
主线程在外部运行循环内运行模态运行循环。在这种情况下,不会处理到主事件循环(主线程)的异步分派。
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()
是一个很好的建议,但不太可能奏效,因为几乎可以肯定的是,当问题发生时,您的主线程没有处理事件。即解决问题,然后dispatch_after()
按照 DarkDust 的建议进行操作。
回答by Arash
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
打印代码没有执行,因为我在串行主线程上调度了一个“同步”块,这导致了死锁。打印正在等待调度完成,调度正在等待打印完成。当您在主串行队列中调度时,您应该使用 dispatch_async。我想如果你使用并发队列,那么调度同步更适合
回答by Shan
If your main thread is busy with modal runloop, then you could try
如果您的主线程正忙于模态运行循环,那么您可以尝试
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, block
});