gpt4 book ai didi

objective-c - NSRunLoop runMode 并不总是处理 dispatch_async

转载 作者:搜寻专家 更新时间:2023-10-30 19:41:46 25 4
gpt4 key购买 nike

我正在尝试更好地了解队列及其工作原理。这个片段是为了测试其行为:

- (void)dispatchQueueTest
{
NSLog( @"Begin test on %@ thread", [NSThread isMainThread] ? @"main" : @"other" );
dispatch_semaphore_t s = dispatch_semaphore_create(0);

dispatch_async( dispatch_get_main_queue(), ^{
NSLog( @"Signalling semaphore" );
dispatch_semaphore_signal(s);
});

NSLog( @"Waiting for worker" );
while( dispatch_semaphore_wait( s, DISPATCH_TIME_NOW ) ) {
NSDate* timeout = [NSDate dateWithTimeIntervalSinceNow:10.f];
// Process events on the run loop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout];
}
dispatch_release(s);
NSLog( @"All sync'd up" );
}

正如预期的那样,它在日志中产生了这个:

Begin test on main thread
Waiting for worker
Signalling semaphore
All sync'd up

奇怪的是,如果从 UIViewController 的 - (void)viewDidAppear:(BOOL)animated 调用此代码,那么它会改变行为。特别是用以下日志进行僵局:

Begin test on main thread
Waiting for worker

我的问题是,为什么在这种情况下通过dispatch_async进行 block 不处理 block ,但在其他情况下会处理 block ?

最佳答案

我有一个项目,我将 PlayerNameEntryViewController 推送到导航 Controller 上。我在 -[PlayerNameEntryViewController viewDidAppear:] 中放置了一个断点。这是命中断点时的堆栈跟踪:

#0  0x0002d3d3 in -[PlayerNameEntryViewController viewDidAppear:] at /Volumes/b/Users/mayoff/t/hotseat2/hotseat2/Home/PlayerNameEntryViewController.m:39
#1 0x00638fbf in -[UIViewController _setViewAppearState:isAnimating:] ()
#2 0x006392d4 in -[UIViewController __viewDidAppear:] ()
#3 0x006395d7 in -[UIViewController _endAppearanceTransition:] ()
#4 0x00648666 in -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] ()
#5 0x007ee90e in -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:] ()
#6 0x007eec17 in -[UINavigationTransitionView _cleanupTransition] ()
#7 0x007eec86 in -[UINavigationTransitionView _navigationTransitionDidStop] ()
#8 0x005a2499 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] ()
#9 0x005a2584 in -[UIViewAnimationState animationDidStop:finished:] ()
#10 0x00497e00 in CA::Layer::run_animation_callbacks(void*) ()
#11 0x02e86515 in _dispatch_main_queue_callback_4CF ()
#12 0x015fe833 in __CFRunLoopRun ()
#13 0x015fddb4 in CFRunLoopRunSpecific ()
#14 0x015fdccb in CFRunLoopRunInMode ()
#15 0x01acd879 in GSEventRunModal ()
#16 0x01acd93e in GSEventRun ()
#17 0x00571a9b in UIApplicationMain ()
#18 0x00002461 in main at /Volumes/b/Users/mayoff/t/hotseat2/hotseat2/main.m:17

通知框架 #11。这是对 _dispatch_main_queue_callback_4CF 的调用。这是运行放在主队列上的 block 的函数。所以 viewDidAppear: 实际上是从一个 block 内部调用的,该 block 使用 dispatch_async 添加到主队列。

主队列是一个串行队列。串行队列的定义是一次只执行一个 block 的队列。如果队列正在执行一个 block ,则该队列上的其他 block 都不能启动。因此,当您递归运行主运行循环时,运行循环会发现它已经在主队列上运行的 block 内,并且不会尝试启动更多 block 。这就是为什么您的信号量信号 block 永远不会运行并且您的应用程序会挂起。

请注意,有时 viewDidAppear: 是从排队 block 内部调用的,有时不是。您不应该依赖任何一种行为。

关于objective-c - NSRunLoop runMode 并不总是处理 dispatch_async,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13657220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com