Iphone 调度组等待GCD
因此,我将向我的服务器发布一系列图像。我想使用GCD异步发布数组,但我还想使执行此操作的方法同步,以便可以传回单个响应对象。然而,dispatch\u group\u wait方法似乎立即返回(而不是等待我的块完成)。这是一个问题,因为我在一个块中使用一个块吗Iphone 调度组等待GCD,iphone,ios,multithreading,concurrency,grand-central-dispatch,Iphone,Ios,Multithreading,Concurrency,Grand Central Dispatch,因此,我将向我的服务器发布一系列图像。我想使用GCD异步发布数组,但我还想使执行此操作的方法同步,以便可以传回单个响应对象。然而,dispatch\u group\u wait方法似乎立即返回(而不是等待我的块完成)。这是一个问题,因为我在一个块中使用一个块吗 NSArray *keys = [images allKeys]; __block NSMutableDictionary *responses = [NSMutableDictionary dictionaryWithCapacity:
NSArray *keys = [images allKeys];
__block NSMutableDictionary *responses = [NSMutableDictionary dictionaryWithCapacity:[images count]];
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < [keys count]; i++) {
__block NSString *key = [keys objectAtIndex:i];
dispatch_group_async(group, queue, ^{
[self postImage:[images objectForKey:key] completionHandler:^(ServerResponse *response){
@synchronized(responses){
if ([response succeeded]) {
NSString *value = [[response data] objectForKey:@"image_token"];
[responses setObject:value forKey:key];
NSLog(@"inside success %@",responses);
} else {
NSString *error = response.displayableError;
if (!error) {
error = @"Sorry something went wrong, please try again later.";
}
[responses setObject:error forKey:@"error"];
[responses setObject:response forKey:@"response"];
}
}
}];
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
NSArray*keys=[images allKeys];
__block NSMutableDictionary*responses=[NSMutableDictionary dictionaryWithCapacity:[图像计数]];
dispatch_group_t group=dispatch_group_create();
调度队列=调度获取全局队列(调度队列优先级默认为0);
对于(int i=0;i<[键计数];i++){
__block NSString*key=[keys objectAtIndex:i];
调度组异步(组、队列、^{
[self postImage:[images objectForKey:key]completionHandler:^(ServerResponse*response){
@同步(响应){
如果([响应成功]){
NSString*值=[[response data]objectForKey:@“image_token”];
[responses setObject:value forKey:key];
NSLog(@“内部成功%@”,响应);
}否则{
NSString*error=response.displayableError;
如果(!错误){
error=@“很抱歉出现问题,请稍后再试。”;
}
[responses setObject:error forKey:@“error”];
[responses setObject:response forKey:@“response”];
}
}
}];
});
}
调度组等待(组、调度时间永远);
调度发布(组);
我只想等待所有的[self postImage]方法从服务器回调并修改响应字典。在没有看到
-postImage:completionHandler:
的代码的情况下,很难说事情安排在哪里,但我假设它们调用了iOS提供的某些东西。如果是这样,块内的处理程序块将异步调度到全局队列,然后立即返回iOS提供的函数或方法。就派遣小组而言,这项工作几乎是立即完成的
在调用dispatch\u group\u wait()
时,没有简单的方法让组等待尚未安排的工作。但是,我们可以添加一个较低级别的thingamajigger,称为信号量,以确保我们的操作以正确的顺序完成,并将其安排在内部(异步)块的范围之外
nsumkeys=[keys count];
dispatch_group_t group=dispatch_group_create();
调度队列=调度获取全局队列(调度队列优先级默认为0);
对于(整数i=0;i
但是这里有一个问题。信号量是一种内核资源。如果我们有100个任务要执行,但是内核只能提供99个信号量呢?坏事™ 发生我们可以重新构建代码,只使用一个信号量,尽管等待它会显得有点不稳定。顺便说一句,这样做实际上完全排除了调度组,所以我们实际上是用信号量替换组。让我们看看
NSUInteger numKeys = [keys count];
// set the count of the semaphore to the number of times it must be signalled before
// being exhausted. Up to `numKeys` waits will actually wait for signals this way.
// Additional waits will return immediately.
dispatch_semaphore_t sem = dispatch_semaphore_create(numKeys);
for (int i = 0; i < numKeys; i++) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (NSUInteger i = 0; i < numKeys; i++) {
__block NSString *key = [keys objectAtIndex:i];
dispatch_async(queue, ^{
[self postImage:[images objectForKey:key] completionHandler:^(ServerResponse *response){
...;
// This decrements the semaphore's count by one. The calling code will be
// woken up by this, and will then wait again until no blocks remain to wait for.
dispatch_semaphore_signal(sem);
}];
});
}
// At this point, all the work is running (or could have already completed, who knows?).
// We don't want this function to continue running until we know all of the blocks
// have run, so we wait on our semaphore a number of times equalling the number
// of signals we expect to get. If all the blocks have run to completion before we've
// waited for all of them, the additional waits will return immediately.
for (int i = 0; i < numKeys; i++) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
// Now all the tasks should have completed.
dispatch_release(sem);
nsumkeys=[keys count];
//将信号量的计数设置为之前必须发出信号的次数
//筋疲力尽。多达'numKeys'等待实际上会以这种方式等待信号。
//其他等待将立即返回。
dispatch_semaphore_t sem=dispatch_semaphore_create(numKeys);
对于(int i=0;i
乔纳森的信号量示例位于targe上
NSUInteger numKeys = [keys count];
// set the count of the semaphore to the number of times it must be signalled before
// being exhausted. Up to `numKeys` waits will actually wait for signals this way.
// Additional waits will return immediately.
dispatch_semaphore_t sem = dispatch_semaphore_create(numKeys);
for (int i = 0; i < numKeys; i++) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (NSUInteger i = 0; i < numKeys; i++) {
__block NSString *key = [keys objectAtIndex:i];
dispatch_async(queue, ^{
[self postImage:[images objectForKey:key] completionHandler:^(ServerResponse *response){
...;
// This decrements the semaphore's count by one. The calling code will be
// woken up by this, and will then wait again until no blocks remain to wait for.
dispatch_semaphore_signal(sem);
}];
});
}
// At this point, all the work is running (or could have already completed, who knows?).
// We don't want this function to continue running until we know all of the blocks
// have run, so we wait on our semaphore a number of times equalling the number
// of signals we expect to get. If all the blocks have run to completion before we've
// waited for all of them, the additional waits will return immediately.
for (int i = 0; i < numKeys; i++) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
// Now all the tasks should have completed.
dispatch_release(sem);
NSUInteger numKeys = [keys count];
NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:numKeys];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (NSUInteger i = 0; i < numKeys; i++) {
__block NSString *key = [keys objectAtIndex:i];
dispatch_async(queue, ^{
[self postImage:[images objectForKey:key] completionHandler:^(ServerResponse *response){
// Basically, nothing more than a obtaining a lock
// Use this as your synchronization primitive to serialize access
// to the condition variable and also can double as primitive to replace
// @synchronize -- if you feel that is still necessary
[conditionLock lock];
...;
// When unlocking, decrement the condition counter
[conditionLock unlockWithCondition:[conditionLock condition]-1];
}];
});
}
// This call will get the lock when the condition variable is equal to 0
[conditionLock lockWhenCondition:0];
// You have mutex access to the shared stuff... but you are the only one
// running, so can just immediately release...
[conditionLock unlock];
NSArray *keys = [images allKeys];
// We will not be reasigning the 'responses' pointer just sending messages to the NSMutableDictionary object __block is not needed.
NSMutableDictionary *responses = [NSMutableDictionary dictionaryWithCapacity:[images count]];
// Create a queue to handle messages to the responses dictionary since mutables are not thread safe.
// Consider this thread the owner of the dictionary.
dispatch_queue_t responsesCallbackQueue = dispatch_queue_create("com.mydomain.queue", DISPATCH_QUEUE_SERIAL);
for (NSString *key in keys) {
// This async call may not be needed since postImage:completionHandler: seems to be an async call itself.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self postImage:[images objectForKey:key] completionHandler:^(ServerResponse *response){
dispatch_async(responsesCallbackQueue, ^{
[responses setObject:response forKey:key];
// Perhaps log success for individual requests.
if (responses.count == keys.count){
NSLog(@"All requests have completed");
// All responses are available to you here.
// You can now either transfer back 'ownership' of the dictionary.
dispatch_async(dispatch_get_main_queue(), ^{
[self requestsHaveFinished:responses];
});
}
});
}];
});
}