【问题标题】:How can I make an asynchronous call synchronous如何使异步调用同步
【发布时间】:2012-01-20 07:44:32
【问题描述】:

我正在重写回调方法以处理 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;

由于我使用的是同步方法,因此在获得数据之前我不能“离开”该方法。此外,我无法预加载所需的数据,因为在我进入请求之前我不知道需要哪个资产。

这对我来说似乎是一个相当棘手的设计问题,如果没有一些重大的黑客攻击,我看不到如何解决这个问题的解决方案。

【问题讨论】:

  • 您是否有机会更改强制您的 HTTP 请求同步的对象? HTTP 请求永远不应该是同步的。如果你不能这样做并且你真的必须解决这个问题,你可以创建并运行一个运行循环,直到请求完成。但我认为这属于您(正确地)希望避免的“主要黑客”类别。
  • @stevex 我将不得不调查是否可以异步进行 HTTP 调用。即使它很hacky,您能否展示我必须如何执行“等待循环”。我以前也遇到过同样的问题,有时我不介意委托回调是否需要一些时间(它甚至可能不在主线程上)所以一个例子会很方便,我不知道怎么做那些街区。

标签: iphone ios architecture objective-c-blocks


【解决方案1】:

编辑: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 获取请求
  • 在等待状态下释放锁
  • 在完成状态下获取锁
  • 在初始状态下释放锁

结果块的逻辑是:

  • 在等待状态下获取锁
  • 在完成状态下释放锁

结果块将阻塞,直到调用线程将条件锁置于等待条件。因此,如果回调是即时的,那么排序就没有问题。

在建立等待条件后,调用线程会一直阻塞,直到在finished条件下释放条件锁。因此,如果结果块尚未完成,它应该等待结果块完成。

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

【讨论】:

    猜你喜欢
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 2010-10-25
    相关资源
    最近更新 更多