简体   繁体   English

如何使异步呼叫同步

[英]How can I make an asynchronous call synchronous

I am overriding a callback method in order to process a response of an HTTP request. 我重写了一个回调方法,以便处理HTTP请求的响应。

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

However, in my request I have to load some data which only works asynchronously: 但是,在我的请求中,我必须加载一些只能异步工作的数据:

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

Since I am in a synchonous method, I can't "leave" the method before I have the data. 由于我使用的是同步方法,因此无法在拥有数据之前“离开”该方法。 Also I can't pre-load the required data since I don't know which asset is required until I am in the request. 另外,由于在请求之前我不知道需要哪种资产,所以我无法预加载所需的数据。

This seems to be quite a tricky design problem for me and I can't see a solution how to solve this without some major hacks. 对于我来说,这似乎是一个棘手的设计问题,而且如果没有一些主要的技巧,我看不到如何解决此问题的解决方案。

EDIT: stevex is absolutely right that your first priority should be to find a way just to make the whole thing asynchronous. 编辑:stevex绝对正确,您的首要任务应该是找到一种使整个事物异步的方法。 Failing that, the answer below should achieve what you want while entrusting the synchronisation steps to the OS for optimal power usage. 失败的话,下面的答案应该可以实现您想要的,同时将同步步骤委托给OS以获得最佳的功耗。

Probably you want to use an NSConditionLock to lock the thing that calls assetForUrl:... immediately after the call, then have your callbacks unlock it. 可能您想使用NSConditionLock在调用后立即锁定调用assetForUrl:...的事物,然后让您的回调对其进行解锁。

A condition lock is a lock with a condition. 条件锁是具有条件的锁。 So you say 'I want the lock when its condition is X' and your thread blocks until it is in that condition. 因此,您说“当条件为X时我想要锁”,并且您的线程将阻塞,直到它处于该状态。 You then have the lock until you unlock it, and you get to specify what condition it will be in immediately upon becoming unlocked. 然后,您将拥有锁,直到您将其解锁为止,然后您可以指定解锁后立即处于何种状态。

The conditions are specified with NSIntegers; 条件由NSIntegers指定;

So there's an aspect of communications built into the lock. 因此,锁中内置了通信的一个方面。

So, for example: 因此,例如:

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];

So, logic on the calling thread is: 因此,调用线程上的逻辑是:

  • acquire the lock in the initial condition 在初始状态下获取锁
  • issue the URL fetch request 发出URL提取请求
  • release the lock in the waiting condition 在等待状态下释放锁
  • acquire the lock in the finished condition 在完成状态下获取锁
  • release the lock in the initial condition 在初始状态下释放锁

And logic on the result blocks is: 结果块上的逻辑是:

  • acquire the lock in the waiting condition 在等待状态下获取锁
  • release the lock in the finished condition 在完成状态下释放锁

The result blocks will block until the calling thread has put the condition lock into the waiting condition. 结果块将一直阻塞,直到调用线程将条件锁置于等待条件中为止。 So there's no problem with sequencing if the callbacks are immediate. 因此,如果回调是即时的,排序就没有问题。

After establishing the waiting condition, the calling thread will block until the condition lock is released in the finished condition. 建立等待条件后,调用线程将阻塞,直到条件锁定在完成条件下释放为止。 So it should then wait for a result block to complete if one hasn't completed already. 因此,如果尚未完成结果块,则应等待结果块完成。

This, of course, assumes that your result blocks are dispatched through GCD by the callee, or if called inline are called from a separate thread. 当然,这假定您的结果块是由被调用者通过GCD调度的,或者如果被调用的是内联的,则是从单独的线程中调用的。 The former is probably a safe assumption. 前者可能是一个安全的假设。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM