dispatch_group_wait在Objective-C中不起作用



创建调度组

dispatch_group_t group = dispatch_group_create();

我正在用调度等待进行3个相同的api调用

[self updateFrequency1];
dispatch_group_wait(group, 3.0);
[self updateFrequency2];
dispatch_group_wait(group, 3.0);
[self updateFrequency3];
dispatch_group_wait(group, 3.0);

进入调度组

-(void)updateFrequency1{
NSLog(@"updating frequency 1");
dispatch_group_enter(group);
[apimanager makeRequest];
}
-(void)updateFrequency2{
NSLog(@"updating frequency 2");
dispatch_group_enter(group);
[apimanager makeRequest];
}
-(void)updateFrequency3{
NSLog(@"updating frequency 3");
dispatch_group_enter(group);
[apimanager makeRequest];
}

离开调度组

-(void)responseReceived:(APIResponse*)response{
NSLog(@"leaving dispatch group");
dispatch_group_leave(group);
}

采用上述方法的控制台日志是

updating frequency 1
updating frequency 2
updating frequency 3
leaving dispatch group
leaving dispatch group
leaving dispatch group

相反,我应该得到

updating frequency 1
leaving dispatch group
updating frequency 2
leaving dispatch group
updating frequency 3
leaving dispatch group

其他部分写得是否正确只是一个猜测,但至少指定的超时时间是错误的。如果您的超时为3秒,则dispatch_group_wait如下所示:

dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 3));

正如梦之风所说(+1(,dispatch_group_wait的第二个参数不正确。应该是

dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));

第二个可能导致您描述的行为的潜在问题是,如果您碰巧在API管理器需要使用的同一线程上"等待"。例如,如果您在主线程上运行,并且API管理器也将代码分派到主线程,那么您将获得相同的行为,因为您的调用方正在等待API管理器可能想要使用的线程。


与您的问题无关,请注意,"发生超时时,组将恢复到其原始状态。"换句话说,如果超时,它将恢复执行,但组计数不变。正因为如此,现在很容易让"输入"one_answers"离开"调用不匹配。

例如,让我们想象一下,您启动了第一个请求,等待了3秒,但它超时了,因为这个请求实际上需要5秒。因此,"等待"超时,调用方恢复执行并在第一个请求仍在进行时启动第二个请求。但是,当第一个调用最终完成时,第一个请求的dispatch_group_leave将不正确地满足第二个请求的dispatch_group_wait最重要的是,这个带有超时的代码乍一看似乎很好,但事实并非如此。您需要检查dispatch_group_wait返回代码以确定如何正确进行。

简而言之,在使用超时时要格外注意正确性。

此外,无论如何,你永远不应该"等待"。等待(无论是组、信号量、锁等(都是低效的。此外,如果你从主队列中进行操作(你永远不应该这样做(,UI可能会冻结,你会引入死锁风险,如果你运气不好,操作系统监督程序会杀死你的应用程序。

我们将使用dispatch_group_notify。或者,更好的是,我们将采用完成处理程序模式,并完全摆脱调度组。

最新更新