我有多个异步任务都依赖于初始异步身份验证步骤才能成功。我正在使用信号量来阻止所有安全任务,直到身份验证完成。它主要用于计时目的,因为任务依赖于在身份验证结束时获得的安全令牌。身份验证涉及网络请求,可能需要几秒钟。
我的代码中的难度似乎是认证后发出的dispatch_semaphore_signal()
仅表示第一个信号量锁可能会继续。第二个将继续阻止。将来可能有许多阻塞任务,都在等待信号量。
我想知道是否有更清洁的方法来解决这个问题。我相信每个等待任务都可以立即发出另一个dispatch_semaphore_signal()
,从而释放下一个任务,依此类推。有没有办法在一次通话中释放所有阻塞信号量?
使用GCD有更清洁的方法吗?我不熟悉GCD,所以代码片段在以下用法的上下文中有所帮助。
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
// in actuality, these 3 may be any where in the app, in different classes, methods, etc
// so a completionHandler is not possible
[self authentication]; // async, could take many seconds
[self authenticatedTask1]; // async
[self authenticatedTask2]; // async
- (void) authentication {
// async url request, assume it is configured here
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
// authenticate
authenticated = TRUE;
secure_token = @"4rjiofwefsdf"; // obtained during auth
dispatch_semaphore_signal(sem);
}];
}
- (void) authenticatedTask1 {
// put on new thread, so semaphore doesn't block program
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if(!authenticated){
// wait until authenticated
dispatch_semaphore_wait(sem)
}
// continue after authenticated, using secure_token
});
}
- (void) authenticatedTask2 {
// put on new thread, so semaphore doesn't block program
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if(!authenticated){
// wait until authenticated
dispatch_semaphore_wait(sem)
}
// continue after authenticated, using secure_token
});
}
答案 0 :(得分:3)
您可以将经过身份验证的任务放入自己的挂起调度队列中,并在身份验证成功后恢复调度队列。
答案 1 :(得分:2)
它不是很优雅但你可以打电话给dispatch_semaphore_signal'紧跟在' dispatch_semaphore_wait'之后。它应该解决问题。
- (void)authenticatedTask1 {
// put on new thread, so semaphore doesn't block program
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
if(!authenticated){
// wait until authenticated
dispatch_semaphore_wait(sem);
dispatch_semaphore_signal(sem); // !!!
}
// continue after authenticated, using secure_token
});
}
答案 2 :(得分:1)
您可以传入要在块中执行的方法以在completltion块中运行,然后您就不需要使用信号量了。此外,您不必费心等待信号量完成dispatch_async
:
[self authenticationWithCompletionBlock:^{
[self authenticatedTask1];
[self authenticatedTask2];
}];
- (void) authenticationWithCompletionBlock:(dispatch_block_t)block {
// async url request, assume it is configured here
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
// authenticate
authenticated = TRUE;
secure_token = @"4rjiofwefsdf"; // obtained during auth
block();
}];
}
如果方法属于同一个类,则可以直接调用方法而不是块。
如果您需要知道两个异步任务(在您的情况下为authenticatedTask1
和authenticatedTask2
)何时完成,那么您需要使用dispatch groups。