简体   繁体   English

dispatch_group_wait 在 Objective-C 中不起作用

[英]dispatch_group_wait is not working in Objective-C

Creating dispatch group创建调度组

dispatch_group_t group = dispatch_group_create();

I am making 3 same api calls with dispatch wait我正在使用调度等待进行 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);

Entering in dispatch group进入调度组

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

Leaving dispatch group离开调度组

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

Console log with the above approach is使用上述方法的控制台日志是

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

Instead, I should get相反,我应该得到

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

It's just a wild guess whether you have some other parts written correctly or not, but at least the time specified for timeout is wrong.您是否正确编写了其他部分只是一个疯狂的猜测,但至少指定的超时时间是错误的。 If your timeout is 3 seconds, then dispatch_group_wait looks as follows:如果您的超时时间为 3 秒,则dispatch_group_wait如下所示:

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

As The Dreams Wind said (+1), the second parameter of dispatch_group_wait is incorrect.正如The Dreams Wind所说(+1), dispatch_group_wait的第二个参数不正确。 It should be它应该是

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

A second potential problem that can cause the behavior you describe is if you happen to “wait” on the same thread your API manager needs to use.可能导致您描述的行为的第二个潜在问题是,如果您碰巧在 API 管理器需要使用的同一线程上“等待”。 Eg, if you were running on the main thread, and the API manager also dispatches code to the main thread, then you will get the same behavior because your caller is waiting on the thread that the API manager may want to use.例如,如果您在主线程上运行,并且 API 管理器也将代码分派到主线程,那么您将获得相同的行为,因为您的调用者正在等待 API 管理器可能想要使用的线程。


Unrelated to your problem, be aware that, “When a timeout occurs, the group is restored to its original state.”与您的问题无关,请注意,“发生超时时,该组将恢复为其原始 state。” In other words, if it times out, it resumes execution, but the group count is unchanged.换句话说,如果超时,它会恢复执行,但组数不变。 Because of this, it is very easy to now let the “enter” and “leave” calls mismatched.正因为如此,现在很容易让“进入”和“离开”调用不匹配。

For example, let us imagine that you started the first request, you waited 3 seconds and it timed out because this request was really going to take 5 seconds.例如,让我们假设您开始了第一个请求,您等待了 3 秒,然后它超时了,因为这个请求实际上需要 5 秒。 So, the “wait” times out, caller resumes execution and initiates the second request while the first is still in progress.因此,“等待”超时,调用者恢复执行并启动第二个请求,而第一个请求仍在进行中。 But when the first call finally finishes, the dispatch_group_wait for the second request will be incorrectly satisfied by the dispatch_group_leave of the first request.但是当第一个调用最终完成时,第二个请求的dispatch_group_wait将被第一个请求的dispatch_group_leave错误地满足 Bottom line, this code with timeouts would appear to be fine at first glance, but it is not.底线,这个带有超时的代码乍一看似乎很好,但事实并非如此。 You need to check the dispatch_group_wait return code to determine how to properly proceed.您需要检查dispatch_group_wait返回代码以确定如何正确进行。

In short, Be extraordinarily careful about correctness when using timeouts.简而言之,使用超时时要特别注意正确性。

Furthermore, you never should “wait”, anyway.此外,无论如何,你永远不应该“等待”。 Waiting (whether groups, semaphores, locks, etc.) is inefficient.等待(无论是组、信号量、锁等)效率低下。 Also, if you do it from the main queue (which you never should), the UI may freeze, you introduce deadlock risks, and if you are unlucky, the OS watchdog process will kill your app.此外,如果您从主队列执行此操作(您永远不应该这样做),UI 可能会冻结,您会引入死锁风险,并且如果您不走运,操作系统看门狗进程将杀死您的应用程序。

We would use dispatch_group_notify .我们将使用dispatch_group_notify Or, better, we would adopt completion handler patterns and get rid of the dispatch group entirely.或者,更好的是,我们将采用完成处理程序模式并完全摆脱调度组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM