Obj-C同步了一个使用块回调的异步方法



我有一个名为getCount:的异步方法,它指向一个web URL,对一些内容进行计数,并在计数完成后调用带有计数的回调。

我有另一个同步的方法,需要获取这些结果,将它们放入消息中,然后返回该消息。以下是两者:

- (NSString *)describe {
    __block bool gotCount = NO;
    [self getCount:^(int count) {
        NSLog(@"Got the count: %i", count);
        _count = count;  // _count is an ivar of the object with this method.
        gotCount = YES;
    }];
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [NSThread sleepForTimeInterval:0.05];
    }
    return [NSString stringWithFormat:@"The count is %i", _count];
}

当我尝试此操作时,我的回调从未被调用。它从不打印

Got the count 0

或者在这种情况下用于计数的任何其他值。

如果我注释掉while循环,那么消息就会打印出来。所以我知道getCount:方法是有效的,只是我的循环在等待它到达时出现了问题。

我需要getCount:保持异步(在其他地方使用它更重要),我需要describe保持同步。我该如何处理?

一件可能的事情:如果你的描述方法在主线程中,那么你也从主线程调用getCount方法,所有的web回调都在主线程但是你用线程睡眠阻塞了主线程->你无法从网络上得到回叫以获得计数。

编辑:

尝试从另一个线程调用getCount方法。使用例如

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   [self getCount:^(int count) {
       NSLog(@"Got the count: %i", count);
       _count = count;  // _count is an ivar of the object with this method.
       gotCount = YES;
   }];
});

编辑2:

我试过这段代码,它运行得很好->getCount方法中的线程可能出了问题。

- (NSString *)describe {
    __block bool gotCount = NO;
    __block NSInteger _count;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSThread sleepForTimeInterval:5.00];
        _count = 5;
        gotCount = YES;
    });
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [NSThread sleepForTimeInterval:0.05];
    }
    return [NSString stringWithFormat:@"The count is %li", _count];
}

一种可行但已退出的方法是在等待时运行runloop:

注意:这依赖于回调与描述方法在同一队列上

请参阅:JSON异步请求[SAME ISSUE]


一个独立的工作示例:

#import <Foundation/Foundation.h>
@interface T : NSObject
- (NSString *)describe;
@end
@implementation T {
    int _count;
}
- (void)getCount:(void (^)(int c)) handler {
    dispatch_async(dispatch_get_global_queue(0,0), ^ {
        sleep(5);
        dispatch_sync(dispatch_get_main_queue(), ^{
            handler(55);
        });
    });
}
- (NSString *)describe {
    __block bool gotCount = NO;
    [self getCount:^(int count) {
        NSLog(@"Got the count: %i", count);
        _count = count;  // _count is an ivar of the object with this method.
        gotCount = YES;
    }];
    // Pause here until the count has been fetched.
    while (!gotCount) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
    return [NSString stringWithFormat:@"The count is %i", _count];
}
@end
int main(int argc, char *argv[]) {
    @autoreleasepool {
        T *t = [T new];
        NSLog(@"describe: %@", [t describe]);
    }
}

最新更新