2011-12-14 174 views
2

我正在重写回调方法以处理HTTP请求的响应。如何使异步调用同步

-(NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path{ 
    NSObject <HTTPResponse> *response; 
    // Here I should load the data 
} 

然而,在我的要求我必须加载一些数据只能异步:

- (void)assetForURL:(NSURL *)assetURL resultBlock:(ALAssetsLibraryAssetForURLResultBlock)resultBlock failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock; 

由于我在synchonous方法,我不能“离开”的方法之前,我有数据。此外,我无法预先加载所需的数据,因为我不知道需要哪些资产,直到我处于请求中。

这似乎是一个相当棘手的设计问题,我看不到一个解决方案如何解决这个问题,没有一些主要的黑客。

+2

您可以更改强制您的HTTP请求同步的对象吗? HTTP请求不应该是同步的。 如果你不能这样做,而且你真的必须解决这个问题,你可以创建并运行一个运行循环,直到请求完成。但我认为这属于你(正确)想要避免的“主要黑客”类别。 – stevex 2011-12-14 15:28:17

回答

5

编辑:stevex是绝对正确的,你的第一优先权应该是找到一种方式,使整个事情异步。否则,下面的答案应该在将同步步骤委托给操作系统以实现最佳用电时达到您想要的效果。

也许你想用一个NSConditionLock锁定呼叫后立即调用assetForUrl:...的东西,然后让你的回调将它解锁。

条件锁是一个条件锁。所以你说'当条件是X时我想要锁',并且你的线程阻塞,直到它处于这种状态。然后,您可以获得锁定,直到您解锁它,并且您可以指定在解锁后立即处于什么状态。

使用NSIntegers指定条件;

所以有锁通信内置的一个方面。

因此,举例来说:

NSConditionLock *conditionLock; // somewhere; an instance variable 

#define kYourClassInitialCondition 0 
#define kYourClassWaitingCondition 1 
// etc 

... 

[conditionLock lockWhenCondition:kYourClassInitialCondition]; 

[whomever assetForUrl:whatever 
      resultBlock:^(args here) 
         { 
         ... do relevant immediate work here ... 

         [conditionLock lockWhenCondition:kYourClassWaitingCondition]; 
         [conditionLock unlockWithCondition:kYourClassFinishedCondition]; 
         } 
      failureBlock:^(args here) 
         { 
         ... as above, same semantics when done ... 
         } 
]; 


[conditionLock unlockWithCondition:kYourClassWaitingCondition]; 

[conditionLock lockWhenCondition:kYourClassFinishedCondition]; 
[conditionLock unlockWithCondition:kYourClassInitialCondition]; 

所以,调用线程上的逻辑是:

  • 获取初始条件锁
  • 问题的URL获取请求
  • 发布处于等待状态的锁
  • 获得完成状态的锁
  • 在初始条件下

和逻辑上的结果块释放锁是:

  • 获取锁在等待状态
  • 释放完成的状态中的锁定

结果块将阻塞,直到调用线程将条件锁定置于等待状态。所以如果回调是立即的,那么顺序没有问题。

建立等待条件后,调用线程将会阻塞,直到条件锁定在完成条件释放。所以如果还没有完成,它应该等待结果块完成。

这当然假设您的结果块是由被调用者通过GCD调度的,或者是如果从单独的线程调用内联调用。前者可能是一个安全的假设。