等待代码执行(已使用调度组)
Waiting for code to execute (already used dispatch groups)
得到下面显示的这段冗长的代码,但我遇到了困难。基本上,代码运行完美,并且完全按照我的意愿执行。但是,它需要在最后打印 "Finished" 之前完成本节中的所有代码 运行。但是,添加信号量或另一个调度组会强制设置断点。可能很明显,但是有人可以给我一些建议吗?
注意:我不能使用底部的调度来调用另一个方法。记住它在一个循环中。
for (id i in arr) {
searchByName = nil;
if ([i containsString:@"word1"] || [i containsString:@"word2"]) {
NSRange searchFromRange = [i rangeOfString:@"ong>"];
NSRange searchToRange = [i rangeOfString:@"</str"];
NSString *substring = [i substringWithRange:NSMakeRange(searchFromRange.location+searchFromRange.length, searchToRange.location-searchFromRange.location-searchFromRange.length)];
[allergens addObject:substring];
if ([substring isEqualToString:@"Examee"] && veg_lac_ovoSafe == TRUE) {
veg_ovoSafe = FALSE;
vegSafe = FALSE;
}
else if ([substring isEqualToString:@"Example"] && veg_lac_ovoSafe == TRUE) { //USE OF HEURISTICS
veg_lacSafe = FALSE;
vegSafe = FALSE;
}
else if ([substring isEqualToString:@"Exam"]) {
pescetarianSafe = TRUE;
vegSafe = FALSE;
veg_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_lac_ovoSafe = FALSE;
pollotarianSafe = FALSE;
}
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
NSCharacterSet *numbersToRemove = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
substring = [[substring componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@""];
searchByName = [[[substring componentsSeparatedByCharactersInSet:numbersToRemove] componentsJoinedByString:@""] lowercaseString];
}
else {
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
NSCharacterSet *numbersToRemove = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSString *searchItem = [[i componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@""];
searchByName = [[[searchItem componentsSeparatedByCharactersInSet:numbersToRemove] componentsJoinedByString:@""] lowercaseString];
}
if (![searchByName isEqualToString:@" "]) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_enter(_groupSearch);
dispatch_async(queue, ^{
[[self databaseQuery:searchByName] observeEventType:FIRDataEventTypeChildAdded
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.value != NULL) {
NSLog(@"%@", snapshot.value);
for (int i=0; i < [[NSString stringWithFormat:@"%@", snapshot.value] length]; i++) {
NSString *x = [NSString stringWithFormat:@"%c", [[NSString stringWithFormat:@"%@", snapshot.value] characterAtIndex:i]];
NSLog(@"%@", x);
if ([x isEqualToString:@"1"]) {
vegSafe = FALSE;
}
else if ([x isEqualToString:@"2"]) {
vegSafe = FALSE;
veg_lacSafe = FALSE;
}
else if ([x isEqualToString:@"3"]) {
vegSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"4"]) { //Could use switch case.
vegSafe = FALSE;
veg_lac_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"5"]) {
pescetarianSafe = FALSE;
}
else if ([x isEqualToString:@"6"]) {
pollotarianSafe = FALSE;
}
}
}
dispatch_group_leave(_groupSearch);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_group_leave(_groupSearch);
}];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_group_wait(_groupSearch, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
dispatch_sync(queue, ^{
//Hi
});
});
}
}
NSLog(@"Finished");
您对 dispatch_group_wait
的使用是在错误的地方。它需要在 for
循环之后,而不是在循环内部。您可以在循环之前创建 queue
并根据需要重用它。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
for (id i in arr) {
searchByName = nil;
// Lots of other code here
if (![searchByName isEqualToString:@" "]) {
dispatch_group_enter(_groupSearch);
dispatch_async(queue, ^{
[[self databaseQuery:searchByName] observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.value != NULL) {
NSLog(@"%@", snapshot.value);
for (int i=0; i < [[NSString stringWithFormat:@"%@", snapshot.value] length]; i++) {
NSString *x = [NSString stringWithFormat:@"%c", [[NSString stringWithFormat:@"%@", snapshot.value] characterAtIndex:i]];
NSLog(@"%@", x);
if ([x isEqualToString:@"1"]) {
vegSafe = FALSE;
}
else if ([x isEqualToString:@"2"]) {
vegSafe = FALSE;
veg_lacSafe = FALSE;
}
else if ([x isEqualToString:@"3"]) {
vegSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"4"]) { //Could use switch case.
vegSafe = FALSE;
veg_lac_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"5"]) {
pescetarianSafe = FALSE;
}
else if ([x isEqualToString:@"6"]) {
pollotarianSafe = FALSE;
}
}
}
dispatch_group_leave(_groupSearch);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_group_leave(_groupSearch);
}];
});
}
}
dispatch_group_wait(_groupSearch, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
NSLog(@"Finished");
由于您在 dispatch_async()
块内调用 dispatch_group_wait()
,您似乎希望 运行 在全局调度队列上异步完成块。正确的方法是使用 dispatch_group_notify()
代替:
dispatch_group_notify(groupSearch, queue, ^{
NSLog(@"Finished")
});
一旦提交给该组的所有块都完成,这将 运行 指定队列上的块,因此不需要 dispatch_async()
或 dispatch_sync()
。此外,在 dispatch_async()
内等待会阻塞 GCD 池中的一个线程,这是一个非常糟糕的主意,因为它们的数量是有限的。这也是使用 dispatch_group_notify()
可以避免的事情。
编辑:以下段落与您更新后的代码不再相关:
此外,正如另一个回答者指出的那样,您可能希望在循环结束后将调用置于 dispatch_group_notify()
,假设您想要一个完成块到 运行在你工作的最后。如果您实际上想要的是一大堆单独的通知,循环中每个 运行 一个通知,那么您可能应该在循环中创建一个新组并使用它。对整个 shebang 使用一个组,然后在循环中设置通知将导致每个通知不仅等待 dispatch_group_leave()
通过循环调用特定 运行,而且等待 all 在 any 运行 上通过循环进行的 dispatch_group_enter()
调用将被平衡。因此,在完成所有工作之前你什么也得不到,然后你会突然一次性发送一大堆完成块,伴随着线程爆炸,因为它们都将提交到全局队列中。这可能不是你想要的。
得到下面显示的这段冗长的代码,但我遇到了困难。基本上,代码运行完美,并且完全按照我的意愿执行。但是,它需要在最后打印 "Finished" 之前完成本节中的所有代码 运行。但是,添加信号量或另一个调度组会强制设置断点。可能很明显,但是有人可以给我一些建议吗?
注意:我不能使用底部的调度来调用另一个方法。记住它在一个循环中。
for (id i in arr) {
searchByName = nil;
if ([i containsString:@"word1"] || [i containsString:@"word2"]) {
NSRange searchFromRange = [i rangeOfString:@"ong>"];
NSRange searchToRange = [i rangeOfString:@"</str"];
NSString *substring = [i substringWithRange:NSMakeRange(searchFromRange.location+searchFromRange.length, searchToRange.location-searchFromRange.location-searchFromRange.length)];
[allergens addObject:substring];
if ([substring isEqualToString:@"Examee"] && veg_lac_ovoSafe == TRUE) {
veg_ovoSafe = FALSE;
vegSafe = FALSE;
}
else if ([substring isEqualToString:@"Example"] && veg_lac_ovoSafe == TRUE) { //USE OF HEURISTICS
veg_lacSafe = FALSE;
vegSafe = FALSE;
}
else if ([substring isEqualToString:@"Exam"]) {
pescetarianSafe = TRUE;
vegSafe = FALSE;
veg_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_lac_ovoSafe = FALSE;
pollotarianSafe = FALSE;
}
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
NSCharacterSet *numbersToRemove = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
substring = [[substring componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@""];
searchByName = [[[substring componentsSeparatedByCharactersInSet:numbersToRemove] componentsJoinedByString:@""] lowercaseString];
}
else {
NSCharacterSet *charactersToRemove = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
NSCharacterSet *numbersToRemove = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
NSString *searchItem = [[i componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:@""];
searchByName = [[[searchItem componentsSeparatedByCharactersInSet:numbersToRemove] componentsJoinedByString:@""] lowercaseString];
}
if (![searchByName isEqualToString:@" "]) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_enter(_groupSearch);
dispatch_async(queue, ^{
[[self databaseQuery:searchByName] observeEventType:FIRDataEventTypeChildAdded
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.value != NULL) {
NSLog(@"%@", snapshot.value);
for (int i=0; i < [[NSString stringWithFormat:@"%@", snapshot.value] length]; i++) {
NSString *x = [NSString stringWithFormat:@"%c", [[NSString stringWithFormat:@"%@", snapshot.value] characterAtIndex:i]];
NSLog(@"%@", x);
if ([x isEqualToString:@"1"]) {
vegSafe = FALSE;
}
else if ([x isEqualToString:@"2"]) {
vegSafe = FALSE;
veg_lacSafe = FALSE;
}
else if ([x isEqualToString:@"3"]) {
vegSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"4"]) { //Could use switch case.
vegSafe = FALSE;
veg_lac_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"5"]) {
pescetarianSafe = FALSE;
}
else if ([x isEqualToString:@"6"]) {
pollotarianSafe = FALSE;
}
}
}
dispatch_group_leave(_groupSearch);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_group_leave(_groupSearch);
}];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_group_wait(_groupSearch, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
dispatch_sync(queue, ^{
//Hi
});
});
}
}
NSLog(@"Finished");
您对 dispatch_group_wait
的使用是在错误的地方。它需要在 for
循环之后,而不是在循环内部。您可以在循环之前创建 queue
并根据需要重用它。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
for (id i in arr) {
searchByName = nil;
// Lots of other code here
if (![searchByName isEqualToString:@" "]) {
dispatch_group_enter(_groupSearch);
dispatch_async(queue, ^{
[[self databaseQuery:searchByName] observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
if (snapshot.value != NULL) {
NSLog(@"%@", snapshot.value);
for (int i=0; i < [[NSString stringWithFormat:@"%@", snapshot.value] length]; i++) {
NSString *x = [NSString stringWithFormat:@"%c", [[NSString stringWithFormat:@"%@", snapshot.value] characterAtIndex:i]];
NSLog(@"%@", x);
if ([x isEqualToString:@"1"]) {
vegSafe = FALSE;
}
else if ([x isEqualToString:@"2"]) {
vegSafe = FALSE;
veg_lacSafe = FALSE;
}
else if ([x isEqualToString:@"3"]) {
vegSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"4"]) { //Could use switch case.
vegSafe = FALSE;
veg_lac_ovoSafe = FALSE;
veg_lacSafe = FALSE;
veg_ovoSafe = FALSE;
}
else if ([x isEqualToString:@"5"]) {
pescetarianSafe = FALSE;
}
else if ([x isEqualToString:@"6"]) {
pollotarianSafe = FALSE;
}
}
}
dispatch_group_leave(_groupSearch);
}
withCancelBlock:^(NSError * _Nonnull error) {
NSLog(@"%@", error.localizedDescription);
dispatch_group_leave(_groupSearch);
}];
});
}
}
dispatch_group_wait(_groupSearch, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
NSLog(@"Finished");
由于您在 dispatch_async()
块内调用 dispatch_group_wait()
,您似乎希望 运行 在全局调度队列上异步完成块。正确的方法是使用 dispatch_group_notify()
代替:
dispatch_group_notify(groupSearch, queue, ^{
NSLog(@"Finished")
});
一旦提交给该组的所有块都完成,这将 运行 指定队列上的块,因此不需要 dispatch_async()
或 dispatch_sync()
。此外,在 dispatch_async()
内等待会阻塞 GCD 池中的一个线程,这是一个非常糟糕的主意,因为它们的数量是有限的。这也是使用 dispatch_group_notify()
可以避免的事情。
编辑:以下段落与您更新后的代码不再相关:
此外,正如另一个回答者指出的那样,您可能希望在循环结束后将调用置于 dispatch_group_notify()
,假设您想要一个完成块到 运行在你工作的最后。如果您实际上想要的是一大堆单独的通知,循环中每个 运行 一个通知,那么您可能应该在循环中创建一个新组并使用它。对整个 shebang 使用一个组,然后在循环中设置通知将导致每个通知不仅等待 dispatch_group_leave()
通过循环调用特定 运行,而且等待 all 在 any 运行 上通过循环进行的 dispatch_group_enter()
调用将被平衡。因此,在完成所有工作之前你什么也得不到,然后你会突然一次性发送一大堆完成块,伴随着线程爆炸,因为它们都将提交到全局队列中。这可能不是你想要的。