我开发了以下方法,用于检查应用程序与服务器的通信能力。该方法执行一个简单的查询,并知道如果得到结果,应用程序应该被连接(基本的ping机制)。
- (BOOL)isAppConnected
{
__block BOOL isConnected = NO;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[[SFRestAPI sharedInstance] performSOQLQuery:@"SELECT id FROM Account LIMIT 1"
failBlock:^(NSError *e) {
isConnected = NO;
NSLog(@"NOT CONNECTED %@", e);
NSLog(@"fail block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);
dispatch_semaphore_signal(semaphore);
} completeBlock:^(NSDictionary *dict) {
isConnected = YES;
NSLog(@"%@", dict);
NSLog(@"complete block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);
dispatch_semaphore_signal(semaphore);
}];
// if the wait times-out we will receive a non-zero result and can assume no connection to SF
//When using: DISPATCH_TIME_FOREVER the app hangs forever!!
int waitResult = dispatch_semaphore_wait(semaphore, 30 * NSEC_PER_SEC);
NSLog(@"waitResult: %d", waitResult);
return isConnected;
}
我正在使用苹果文档中建议的"dispatch_semaphore_wait"
我的目标是等待响应或短暂的超时,以确定我们是否真的有一个有效的连接。
在上面的代码中,"dispatch_semaphore_wait"实际上从不等待,即执行不会在那一行停止,而是立即继续(总是返回49作为dispatch_semaphore_waite调用的结果)。除非我使用DISPATCH_TIME_FOREVER,否则应用程序将永远挂起。。。
目前,我正在从主线程调用此方法。我知道这是一个坏主意,但我希望在重构之前看到它按预期工作。
是什么导致了这种行为?谢谢
- (BOOL)isAppConnected
{
__block BOOL isConnected = NO;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// Add this code...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[SFRestAPI sharedInstance] performSOQLQuery:@"SELECT id FROM Account LIMIT 1"
failBlock:^(NSError *e) {
isConnected = NO;
NSLog(@"NOT CONNECTED %@", e);
NSLog(@"fail block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);
dispatch_semaphore_signal(semaphore);
} completeBlock:^(NSDictionary *dict) {
isConnected = YES;
NSLog(@"%@", dict);
NSLog(@"complete block ON THE MAIN THREAD? %hhd", [NSThread isMainThread]);
dispatch_semaphore_signal(semaphore);
}];
});
int waitResult = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"waitResult: %d", waitResult);
return isConnected;
}
首先,如果您的fail
和complete
块在主线程上被调用,那么您将永远等待,或者直到您指定的超时"超时"
原因是在调用dispatch_semaphore_wait
之后,主线程开始等待。然后,如果performSOQLQuery调用主线程上的块,则在超时"超时"之前不会发生任何事情。
现在,粗略地说,如果您指定了一个永远离开的时间,信号量将永远不会发出信号或放手,这意味着您的主线程将永远等待。
将等待代码更改为:永远不要让主线程等待
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
int waitResult = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"waitResult: %d", waitResult);
});
并且不要像您正在做的那样返回Bool,因为这是一个漫长的操作,您希望使用一个有结果的块。
还要确保performSOQLQuery()方法不在主线程上。